最好的选择? 在编译之前编辑字节码(asm)或编辑java文件

目标

  • 检测变量之间的比较和变量的复制
  • 在操作发生的行附近注入代码
  • 代码的目的:每次运行类都会使计数器增加

通用:计算执行后使用某些参数进行的比较和复制的数量

2个选项

注意:我总是有一个.java文件

1)编辑java文件


找到与正则表达式的比较并在行附近注入代码片段然后编译该类(我的应用程序使用JavaCompiler)

2)使用ASM字节码工程


还检测我想跟踪的事件的位置并将片段注入字节码然后使用(已经编译但已修改)的类

我的问题

什么是最好/最干净的方式? 有一个更好的方法吗?

如果你选择Java路由,你不想使用正则表达式 – 你想要一个真正的java解析器。 这可能会影响您的决定。 请注意,Oracle JVM包含一个,作为实现java编译器的内部私有类的一部分,因此如果您不愿意,您实际上不必自己编写一个。 但解码Oracle AST也不是一个5分钟的任务。 而且,当然,如果这很重要,那么使用它是不可移植的。

如果你使用ASM路由,字节码最初将更容易分析,因为语义更简单。 在解决方案的净时间方面,分析的简单性是否超过不熟悉程度是未知的。 最后,就生成的代码而言,两者都不是“更好”。

只看生成的java源代码并“知道”你所看到的是什么以及为调试等进行类文件的原始转储,这显然很简单,但由于你已经存在,显然简单了Java语言的舒适性。 一旦你花了一些时间挖掘字节代码,也会变得舒适。 只是一个问题,是否值得你花时间到达那里。

一般来说,这取决于你对任何一种选择的舒适度以及对性能方面的重要性。 字节码操作将更快,更简单,但您必须了解字节码如何工作以及如何使用ASM框架。

拦截变量访问可能是ASM最简单的用例之一。 你可以在这篇AOSD’07论文中找到一些更复杂的场景。

以下是拦截变量访问的简化代码:

ClassReader cr = ...; ClassWriter cw = ...; cr.accept(new MethodVisitor(cw) { public void visitVarInsn(int opcode, int var) { if(opcode == ALOAD) { // loading Object var ... insert method call } } }); 

如果是我,我可能会使用ASM选项。

如果您需要有关ASM的教程,我偶然发现了这个用户编写的教程, 请单击此处