2017-11-14 3 views
0

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을 호출한다는 것을 알았습니다. 왜 이런 일이 생길까요?

답변

0

ASM의 API 버전이 변경되었고 MethodVisitor.visitMethodInsn의 시그니처가 버전 4와 5에서 다르다는 것이 나타났습니다. 동적 바인딩은 더 이상 무시 방법으로 인식하지 않습니다.

나는 누구의 서명 지금

public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) 
입니다 InvokeFinder.visitMethodInsn에 누락 된 매개 변수를 추가하여이 문제를 해결할 수
관련 문제