ASM:ClassReader 未调用 MethodVisitor 的方法
ASM: MethodVisitor's methods are not called by the ClassReader
我正在编写一个使用 ASM 5 执行字节码静态分析的小工具。我将我的输入 Java class 提供给触发自定义 ClassVisitor 事件的 ClassReader。如果满足某些条件,我的 ClassVisitor 将 visitMethod
覆盖为 return 我的自定义 MethodVisitor,如果不满足,则覆盖 null
。
问题是,ClassReader 从不调用 MethodVisitor 的方法;我用 NetBeans 调试了它,我看到访问者被正确地 returned(它不是 null
)但是执行仍然没有进入 visitMethodInsn
,即使有 are 我用于测试的 classes 中的方法说明。
以前用过ASM,但是第一次遇到这个问题
这是我的 MyClassVisitor.visitMethod
代码:
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
InvokeFinder visitor;
if(condition.isMet()) {
visitor = new InvokeFinder(api);
visitor.doStuff();
} else {
visitor = null;
}
return visitor;
}
这里是InvokeFinder
的代码,在执行过程中从不输入:
public class InvokeFinder extends MethodVisitor {
public InvokeFinder(int api) {
super(api);
}
void unrelatedMethod(String parameter) {
doStuff(parameter);
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
switch (opcode) {
case Opcodes.INVOKEVIRTUAL:
case Opcodes.INVOKESPECIAL:
case Opcodes.INVOKEDYNAMIC:
doSomething();
break;
case Opcodes.INVOKEINTERFACE:
doSomethingElse();
break;
case Opcodes.INVOKESTATIC:
doSomethingDifferentAgain();
break;
default: break;
}
}
}
最后这是我正在测试的class(这并不意味着永远执行,它的唯一目的是编译然后由我的工具分析):
public class MyTestClass{
public MyTestClass(String s) {
System.out.println( "Function Name" );
}
public static void main(String args[]) {
CGraph g = new CGraph("entry");
g.enterBF(new CGVisitor() {
@Override
public void nodeOperations(CGraph graph, CGraphNode currentNode) {
System.out.println("20");
}
@Override
public String getString() {
throw new UnsupportedOperationException("No string can be returned from this anonymous implementation of CGVisitor.");
}
});
a( 11 );
}
public static void a(int n) {
b( n );
}
public static void b(int m) {
int n;
if (m >= 10)
a( m-1 );
else
System.out.println(m);
}
}
我仔细检查了上面的 visitMethod
方法总是被执行,return 是 InvokeFinder
的一个非空实例并且这个实例永远不会被执行;怎么可能在这些条件下 InvokeFinder.visitMethodInsn
永远不会被 ClassReader 调用,即使 MyTestClass
的某些方法中有调用指令(例如内部方法 a(int)
)?
编辑:进一步调试,我发现 ClassReader 调用默认 MethodVisitor.visitMethodInsn
而不是调用覆盖版本 InvokeFinder.visitMethodInsn
。为什么会这样?
原来我更改了 ASM 的 API 版本并且 MethodVisitor.visitMethodInsn
的签名在版本 4 和 5 之间不同。动态绑定不再将其识别为覆盖方法。
我可以通过将缺少的参数添加到 InvokeFinder.visitMethodInsn
来解决这个问题,InvokeFinder.visitMethodInsn
现在的签名是
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf)
我正在编写一个使用 ASM 5 执行字节码静态分析的小工具。我将我的输入 Java class 提供给触发自定义 ClassVisitor 事件的 ClassReader。如果满足某些条件,我的 ClassVisitor 将 visitMethod
覆盖为 return 我的自定义 MethodVisitor,如果不满足,则覆盖 null
。
问题是,ClassReader 从不调用 MethodVisitor 的方法;我用 NetBeans 调试了它,我看到访问者被正确地 returned(它不是 null
)但是执行仍然没有进入 visitMethodInsn
,即使有 are 我用于测试的 classes 中的方法说明。
以前用过ASM,但是第一次遇到这个问题
这是我的 MyClassVisitor.visitMethod
代码:
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
InvokeFinder visitor;
if(condition.isMet()) {
visitor = new InvokeFinder(api);
visitor.doStuff();
} else {
visitor = null;
}
return visitor;
}
这里是InvokeFinder
的代码,在执行过程中从不输入:
public class InvokeFinder extends MethodVisitor {
public InvokeFinder(int api) {
super(api);
}
void unrelatedMethod(String parameter) {
doStuff(parameter);
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
switch (opcode) {
case Opcodes.INVOKEVIRTUAL:
case Opcodes.INVOKESPECIAL:
case Opcodes.INVOKEDYNAMIC:
doSomething();
break;
case Opcodes.INVOKEINTERFACE:
doSomethingElse();
break;
case Opcodes.INVOKESTATIC:
doSomethingDifferentAgain();
break;
default: break;
}
}
}
最后这是我正在测试的class(这并不意味着永远执行,它的唯一目的是编译然后由我的工具分析):
public class MyTestClass{
public MyTestClass(String s) {
System.out.println( "Function Name" );
}
public static void main(String args[]) {
CGraph g = new CGraph("entry");
g.enterBF(new CGVisitor() {
@Override
public void nodeOperations(CGraph graph, CGraphNode currentNode) {
System.out.println("20");
}
@Override
public String getString() {
throw new UnsupportedOperationException("No string can be returned from this anonymous implementation of CGVisitor.");
}
});
a( 11 );
}
public static void a(int n) {
b( n );
}
public static void b(int m) {
int n;
if (m >= 10)
a( m-1 );
else
System.out.println(m);
}
}
我仔细检查了上面的 visitMethod
方法总是被执行,return 是 InvokeFinder
的一个非空实例并且这个实例永远不会被执行;怎么可能在这些条件下 InvokeFinder.visitMethodInsn
永远不会被 ClassReader 调用,即使 MyTestClass
的某些方法中有调用指令(例如内部方法 a(int)
)?
编辑:进一步调试,我发现 ClassReader 调用默认 MethodVisitor.visitMethodInsn
而不是调用覆盖版本 InvokeFinder.visitMethodInsn
。为什么会这样?
原来我更改了 ASM 的 API 版本并且 MethodVisitor.visitMethodInsn
的签名在版本 4 和 5 之间不同。动态绑定不再将其识别为覆盖方法。
我可以通过将缺少的参数添加到 InvokeFinder.visitMethodInsn
来解决这个问题,InvokeFinder.visitMethodInsn
现在的签名是
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf)