ASM 5를 사용하여 바이트 코드의 정적 분석을 수행하는 작은 도구를 작성하고 있습니다. 사용자 입력 ClassVisitor의 이벤트를 트리거하는 ClassReader에 입력 Java 클래스를 제공합니다. My ClassVisitor는 특정 조건이 충족되면 visitMethod
을 사용자 정의 MethodVisitor로 반환하고 그렇지 않으면 null
을 반환합니다.ASM : MethodVisitor의 메소드가 ClassReader에 의해 호출되지 않았습니다.
문제는 ClassReader가 MethodVisitor의 메서드를 호출하지 않는다는 것입니다. NetBeans를 사용하여 디버깅 한 결과 방문객이 올바르게 반환되었지만 (null
) visitMethodInsn
을 입력하지 않았음에도 불구하고 이 메소드 테스트에 사용되는 클래스의 메소드 명령어 인 경우에도 계속 실행됩니다.
이전에는 ASM을 사용했지만이 문제가 발생한 것은 이번이 처음입니다. 여기
는MyClassVisitor.visitMethod
내 코드입니다 :
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;
}
}
}
을 그리고 마지막으로이 내가에 대한 테스트있어 클래스 (이다 : 여기
@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 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
메서드가 항상 실행되는지 확인하고 null이 아닌 InvokeFinder
인스턴스를 반환하며이 인스턴스는 결코 실행되지 않습니다. 어떤 경우에 MyTestClass
(예 : 내부 메서드 a(int)
)의 호출 명령어가 있더라도 InvokeFinder.visitMethodInsn
이 ClassReader에 의해 호출되지 않을 수 있습니다.
편집 : 디버깅을 더 진행하면 ClassReader가 재정의 버전 InvokeFinder.visitMethodInsn
을 호출하는 대신 기본값 인 MethodVisitor.visitMethodInsn
을 호출한다는 것을 알았습니다. 왜 이런 일이 생길까요?