在编译的Java类中重写方法调用

我希望在解析编译的类文件时,在方法体内调用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源文件以供使用,但我更喜欢更优雅的解决方案,例如使用reflection生成新的编译类文件。

有什么想法吗 ?

正如@djna所说,可以在加载字节码文件之前对其进行修改,但您可能不希望这样做:

  • 执行代码修改的代码可能很复杂且难以维护。
  • 已修改的代码可能难以调试。 首先,源级调试器将显示不再与您实际编辑的代码对应的源代码。

在某些情况下,字节码重写很有用。 例如,JDO实现使用字节码重写来将对象成员提取替换为对持久性库的调用。 但是,如果您可以访问这些文件的源代码,则可以通过预处理(或生成)源代码获得更好(即更易维护)的解决方案。

编辑:AOP或Groovy听起来也像是可行的替代方案,具体取决于您预期的重写程度。

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更费力。

另一种可能性是更改multiply或divide方法本身,而不是尝试更改调用该操作的代码的所有实例。 这将是BCEL(或ASM)的一条更容易的道路。

指定了编译Java的字节代码格式,并且存在操纵它的产品。

该库似乎具有您需要的function。 我不知道可靠地进行这些转换是多么容易。

如果您不介意使用Groovy,可以拦截对B.multiply的调用并将其替换为C.divide 。 你可以在这里找到一个例子。

在提前执行这些操作要容易得多,在启动应用程序之前修改磁盘上的可执行文件。 在运行时操作内存中的代码比在C / C ++中操作内存中的代码更容易出错。 你为什么需要这样做?