我正在尝试在ASM中实现需要两次遍历每个方法的转换。第一个收集有关需要检测的位置的信息(与跳转目标有关,这就是我需要两次通过的原因),第二个完成收集的信息并添加检测。这也意味着我必须在开始第二遍之前完成第一遍(即处理所有指令)。这就是为什么手册中讨论的正常链接模式不起作用的原因。
我的问题是:有优雅便捷的方法吗?
到目前为止,我能想出的唯一解决方案是在第一个访问者中调用visitEnd()中的第二个访问者。大纲看起来像这样
public class Pass1Visitor extends MethodVisitor {
...
public void visitEnd() {
//do stuff the call the second visitor
thisMethodNode.accept( new Pass2Visitor() );
}
}
我不太喜欢这个解决方案,因为我怀疑将来我将不得不链接更多的访客,我可能希望能够挑选和选择。哪个是真的不可能。
答案 0 :(得分:0)
如果你需要两次通过字节码,那就是你用ASM做的。树包(即MethodNode)将保存所有访问事件,并且可以在调用accept()方法时重放它们。传递下一个访客是一个坏主意,但传递访问者并没有错。请参阅JSRInlinerAdapter中关于ASM的AOSD.07 paper中的“内联方法”部分的实施{/ 3}}。
所以,你的例子看起来像这样:
public class Pass1Visitor extends MethodNode {
MethodVisitor nextVisitor;
public Pass1Visitor(MethodVisitor nextVisitor) {
this.nextVisitor= nextVisitor;
}
...
public void visitEnd() {
//do stuff the call the second visitor
thisMethodNode.accept( nextVisitor );
}
}