我知道可以用Reflection做很好的事情,例如调用方法或改变字段的值。但是,是否可以在运行时和以编程方式进行更重的代码修改?
例如,如果我有一个方法:
public void foo(){
this.bar = 100;
}
我可以编写一个修改此方法内部的程序,注意它为字段分配一个常量,并将其转换为以下内容:
public int baz = 100;
public void foo(){
this.bar = baz;
}
也许Java并不是真正做这种事情的语言 - 如果没有,我愿意接受语言的建议,这些语言可以让我基本上以这种方式重新分析或检查代码,并能够改变它如此精确。我可能会在这里做梦,所以请告诉我是否也是这样。
答案 0 :(得分:0)
只需添加朋友的建议--Apache Commons的BCEL看起来很棒:
http://commons.apache.org/bcel/manual.html
字节代码工程库(Apache Commons BCEL™)旨在实现 为用户提供分析,创建和操作的便捷方式(二进制) Java类文件(以.class结尾的文件)。类由以下表示 包含给定类的所有符号信息的对象: 特别是方法,字段和字节代码指令。 这些对象可以从现有文件中读取,由a转换 程序(例如,运行时的类加载器)并再次写入文件。 一个更有趣的应用程序是从中创建类 在运行时划伤。字节码工程库(BCEL)可能是 如果你想了解Java虚拟机(JVM)也很有用 以及Java .class文件的格式。
答案 1 :(得分:0)
您正在寻找允许您进行字节码操作的软件,有几个框架可以实现这一点,但目前最知名的两个是:
在Java类中在运行时执行字节码修改时请记住以下内容:
如果在类加载器加载类之后更改类的字节码,则必须找到一种方法来重新加载它的类定义(通过类加载技巧或使用热交换功能)
如果您更改了类界面(示例添加新方法或字段),您只能通过反射来访问它们。
答案 2 :(得分:0)
可以公平地说,Java的设计并没有考虑到这个目的,但是你可以潜在地做到这一点。如何以及何时取决于练习的最终目的。有两种选择:
在源代码级别,您可以使用Java Compiler API来 将任意代码编译成类文件(然后可以加载)。
在字节码级别,您可以编写安装a的代理 ClassFileTransformer任意改变“在飞行中”的班级 因为它已加载。在实践中,如果你这样做,你也可能 利用诸如BCEL (Bytecode Engineering Library)之类的库来更轻松地操作类。
答案 3 :(得分:0)
你的意思是这样吗?
String script1 = "println(\"OK!\");";
eval( script1 );
script1 += "println(\"... well, maybe NOT OK after all\");";
eval( script2 );
输出:
OK!
OK!
... well, maybe NOT OK after all
...使用Java的脚本扩展。 Groovy和其他类似的东西可能会让你做你想做的事。我编写了一个脚本扩展,它通过几乎无缝地自己反射与Java集成;如果您对细节感兴趣,请与我联系。
答案 4 :(得分:0)
您想要调查program transformation systems (PTS),它提供了在源级别解析和转换语言的一般工具。 PTS提供重写规则,实际上,“如果您看到此模式,请使用目标语言的表面语法替换该模式”。这是使用完整的解析器完成的,因此重写规则实际上对语言语法而不是文本进行操作;与基于正则表达式的工具不同,这样的重写规则显然不会尝试修改注释中的类似代码的文本。
我们的DMS软件再造工具包就是其中之一。它不仅提供通常的解析,AST构建和漂亮打印(再现可编辑的源代码和注释),还支持符号表和控制以及数据流分析。几乎所有有趣的转换都需要这些。 DMS还有各种Java方言以及许多其他语言的前端。
字节变换器的存在是因为它们更容易构建; “解析”字节码非常容易。当然,您不能使用字节码转换器进行永久性的源更改,因此它的用处不大。