我希望在解析编译的类文件时,在方法体内调用anther类来替换对给定类的调用...
换句话说,是否有一种方法可以检测方法中给定类的用法,并使用类似javaassist之类的方法替换方法的那一部分。
例如..如果我有
的编译版本class A { public int m() { int i = 2; B.multiply(i,i); return i; } }
是否有一种方法可以检测B的使用,然后改变代码来执行
class A { public int m() { int i = 2; C.divide(i,i); return i; } }
我知道替代方法是编写一个解析器来grep源文件以供使用,但我更喜欢更优雅的解决方案,例如使用反射来生成新的编译类文件。
有什么想法吗?
答案 0 :(得分:3)
正如@djna所说,可以在加载前修改字节码文件,但您可能不想这样做:
字节码重写在某些情况下很有用。例如,JDO实现使用字节码重写来将对象成员提取替换为对持久性库的调用。但是,如果您可以访问这些文件的源代码,则可以通过预处理(或生成)源代码获得更好(即更易维护)的解决方案。
编辑:AOP或Groovy听起来也像是可行的替代方案,具体取决于您预期的重写程度。
答案 1 :(得分:2)
我最近查看了许多用于读取Java类文件的库。 BCEL是最快的,拥有最少数量的依赖项,开箱即用,并且有一个非常简单的API。我更喜欢BCEL到ASM,因为ASM有更多的依赖关系(虽然API据说更简单)。
如前所述,AspectJ是另一种可行的选择。BCEL非常简单。您可以通过三行代码获取方法列表:
ClassParser cp = new ClassParser( "A.class" );
JavaClass jc = cp.parse();
Method[] m = jc.getMethods();
还有其他API工具可供进一步内省,我相信,包括在方法中获取指令的方法。但是,这种解决方案可能比AspectJ更费力。
另一种可能性是更改multiply或divide方法本身,而不是尝试更改调用该操作的代码的所有实例。这对BCEL(或ASM)来说是一条更容易的道路。
答案 2 :(得分:1)
指定了编译Java的字节代码格式,并且存在操纵它的产品。
此library似乎具备您所需的功能。我不知道可靠地进行这些转换是多么容易。
答案 3 :(得分:1)
如果您不介意使用Groovy,可以拦截对B.multiply
的调用并将其替换为C.divide
。您可以找到示例here。
答案 4 :(得分:0)
提前执行这些操作要容易得多,在启动应用程序之前修改磁盘上的可执行文件。在运行时操作内存中的代码比在C / C ++中操作内存中的代码更容易出错。你为什么需要这样做?