【发布时间】:2022-01-03 07:16:26
【问题描述】:
我正在尝试使用 Java ASM 编写一个简单的程序来计算执行的 Java 字节码的数量。
这个post 提出了同样的问题,并且有一个使用 ASM 的解决方案。但是,答案指向一个不再可用的链接。
我探索了 Java ASM API,发现了似乎允许此任务的基于树的 API。以下是我目前取得的成果。
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
public class Executor {
public static void main(String[] args) throws IOException {
Contract c = new Contract();
c.execute();
FileInputStream is = new FileInputStream("target/classes/Contract.class");
ClassReader cr = new ClassReader(is);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
final ClassNode classNode = new ClassNode();
cr.accept(classNode, 0);
classNode.fields.add(new FieldNode(Opcodes.ACC_PUBLIC,
"Counter", "I", null, new Integer(-1)));
FileOutputStream fos = new FileOutputStream("target/classes/ModifiedContract.class");
classNode.accept(cw);
fos.write(cw.toByteArray());
fos.close();
}
}
到目前为止,我所做的是将全局计数器添加到 .class 文件(字节码)中。
据我了解,下一步是在每个字节码执行后添加一个 counter++ 语句。
从文档中我发现 MethodNode 中的InsnList 对象对应一个字节码:这样对吗?
如果是这样,我可以为每个字节码添加一个 counter++ 语句的最佳方法是什么,以便最后得到执行的字节码数量(我对字节码的总数不感兴趣,只对执行的字节码感兴趣)
(我是 Java + ASM 世界的新手)
谢谢
【问题讨论】:
-
您不想将该字段声明为
static吗?进一步注意,在这里指定一个常量值是没有意义的,因为该字段不是常量。如果你想要一个可变字段的初始值,你必须在构造函数中分配它(或者如果字段是static,则为类初始化器)。但是为什么不使用默认值零,这是一个适合计数器的初始值呢?然后,增加一个static字段包含四个指令,getstatic、iconst_1、iadd、putstatic,而增加一个非static字段需要六个:aload_0、getfield、添加一、aload_0、putfield。 -
@Holger 感谢您的评论。我认为你是正确的,我应该将它声明为一个类变量 - 静态的。我不确定我是否正确理解了您增加静态计数器的方法。可以给个代码sn-p吗?
-
一般来说,当你想做字节码操作的时候,你应该知道The Java® Virtual Machine Specification。第 6 章描述了所有字节码指令,但第 3 章也很有价值,因为它展示了高级构造如何映射到这些指令。了解其他章节中的其他内容也不会有什么坏处……
标签: java bytecode java-bytecode-asm