2013-04-27 3 views
3

내 목표는 일부 Java 바이트 코드의 모든 기본 블록의 시작 부분에 작은 양의 코드를 계측하는 것입니다. 기본 블록을 통해 실행 경로를 기록하는 것이 목적입니다. 현재 Javassist를 사용하여 메소드의 시작과 끝 부분에 몇 가지 코드를 준비하고 있지만, Javassist API를 사용하여 더 세밀한 바이트 코드 위치를 계측 할 때 벽을 뚫고 실행했습니다.javaagent를 사용하여 Java로 로그인하는 기본 블록

Javassist는 메소드 내 모든 기본 블록을 나타내는 Block []을 제공합니다. 기본 블록은 바이트 코드 위치를보고 할 수 있으므로 내 계측이 필요한 곳을 알 수 있습니다. Javassist의 계측은 CtMethod.insertAt (int sourceCodeLineNumber, String newSourceCode)이지만, 소스 코드 바이트 코드 이 아닌 라인 번호가 사용 되었기 때문에 this 질문에 나타나는 문제가 발생합니다. 확실히이 점에서 그 문제에 대한 해결책은 없다.)

[질문

: 변수 자체와 Javassist 계측에서 때 어떻게 계측 를 사용하는 방법 내에서 변수에 값을 할당 할 수 있습니다. 나는 다른 도구를 사용하지 않는 것이 좋지만,이 시점까지 얻을 수있는 도움을 받고 있습니다.

변수를 사용하여이와 Javassist과 같이 선언됩니다

//m is a CtMethod   
try { m.addLocalVariable("someVar", ClassPool.getDefault().get("SomePackage.SomeClass")); } 
catch (NotFoundException e) { e.printStackTrace(); } 

내 최악의 경우 어떻게 든 악기와 Javassist 전체 방법/클래스를 통해 진행 반복자와 바이트 코드를 삽입 스택 변수를 추정한다 시나리오,하지만 그 정말 심술 궂을거야. 내 메소드는 정수 입력 (블록 ID) 및 무효 출력을 가지고 있기 때문에 자바 바이트 코드는 모든 기본 블록의 시작 부분에 다음과 같을 것이다 : 나는 변수 ID를 얻을 것으로

ALOAD 6 //6 is my new Javassist variable ID, however I don't think I can get Javassist to actually tell it to me 
ICONST_1 //My parameters, which is an int. I'd have to switch statement between ICONST, SIPUSH, and ALOAD depending on basic block's index size 
INVOKEVIRTUAL SomePackage/SomeClass.SomeMethod(I)V 

답변

0

가장 좋은 방법 ConstPool 테이블에서 변수를 삽입 한 후 최대 크기를 테스트하고 있습니다.

try { m.addLocalVariable(mse, ClassPool.getDefault().get("org.javadynamicanalyzer.MethodStackEntry")); } 
    catch (NotFoundException e) { e.printStackTrace(); } 

    int mseCSindex=m.getMethodInfo().getCodeAttribute().getMaxLocals()-1; 

다음으로 테이블에서 invokevirtual 인덱스가 필요합니다. 이것은 발견하기에 약간 빨랐다. 아래 코드는 찾고있는 함수에 대해 ConstPool 테이블을 검색합니다. 내가 찾고있는 기능은 org.javadyanmicanalyzer.MethodStackEntry.setBlockID(int)입니다.

 int virtFunIndex=-1; 
     boolean found=false; 
     while(found==false){ 
      ++virtFunIndex; 
      try{ 
       int id=cp.isMember("org.javadynamicanalyzer.MethodStackEntry", "setBlockIndex", virtFunIndex); 
       if(id!=0){ 
        found=true; 
       } 
      } 
      catch(NullPointerException | ClassCastException e){} 
     } 

마지막으로, 악기로 각 블록의 시작에 필요한 :

 int len=new ControlFlow(m).basicBlocks().length; 
     for(int i=0; i<len; ++i){ 
      Block thisbb=new ControlFlow(m).basicBlocks()[i]; //we have to re-evaluate the control flow every time we add new code 
      CodeIterator itr=m.getMethodInfo().getCodeAttribute().iterator(); 

      int pos=thisbb.position(); 
      byte[] newCode=new byte[]{Bytecode.ALOAD, //loads the mse class 
             mseCSindex, //my mse local variable 
             Bytecode.ICONST_0, //the input to the virtual function 
             Bytecode.INVOKEVIRTUAL, //execute the virtual function 
             (byte) virtFunIndex>>8, //virtual function's address 
             (byte) virtFunIndex && 0xFF}; 

      int n = itr.insertAt(pos, newCode); 
     } 

그것은 더러운 그리고 완전히 자신을 파괴 할 가능성이있다,하지만 그것은했다!