重写编译的Java类中的方法调用(Rewriting method calls within com

2019-07-31 21:52发布

我想一个方法体中调用替换与调用给定类花药类,同时解析编译的类文件...
或换一种说法,就是存在的方法中的检测给定类的用途和替换使用类似的方法的只是一部分的方法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为用途的源文件,但我宁愿一个更优雅的解决方案,如使用反射来生成新编译的类文件。

有什么想法吗 ?

Answer 1:

作为@djna说,这是可以修改的字节码文件加载之前,但你可能不希望这样做:

  • 该做的代码修改的代码很可能是复杂和难以维护。
  • 已被修改的代码很可能是难以调试。 一开始,源级调试器会告诉你,不再符合你实际上是在编辑代码的源代码。

字节码重写是在某些情况下是有用的。 例如,JDO实现使用字节码重写来替换对象构件与呼叫到持久性库取出。 但是,如果你有机会到源代码,这些文件,你会通过预处理(或发电)的源代码获得更好的(即更好的可维护性)的解决方案。

编辑:和AOP或Groovy声如可行的替代方案也取决于重写你预计以后的程度。



Answer 2:

BCEL或ASM 。

我最近看了一些图书馆的阅读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的更费力。

另一种可能性是改变乘除法方法本身,而不是试图改变调用操作的代码的所有实例。 这将是一个更容易的道路采取与BCEL(或ASM)。



Answer 3:

为编译Java字节码的格式是指定的,产品存在操纵它。

该库似乎有你所需要的能力。 我不知道它是多么容易可靠地做这些转换。



Answer 4:

如果你不介意使用Groovy,你可以拦截调用B.multiply ,取而代之的是C.divide 。 你可以找到一个例子在这里 。



Answer 5:

它更容易名列前茅的时间,在磁盘上的可执行文件启动应用程序前修改执行这些操作。 在运行时存储器操作的代码是更容易比下,在存储器操作代码/ C ++错误。 你为什么要这么做?



文章来源: Rewriting method calls within compiled Java classes