2014-03-06 12 views
0

Java 코드에서 사용되지 않는 사용되지 않는 변수 (인수, 지역 변수, 클래스 멤버 변수)를 식별해야합니다. 기본적으로 BCEL을 사용하여 바이트 코드에 액세스하고 내 목표에 도달해야합니다.Java 코드에서 사용되지 않는 변수를 확인하십시오.

ClassGen을 사용하여 모든 메소드를 호출 한 다음 MethodGen을 사용하여 모든 로컬 변수와 함수 인수를 관리했습니다. 그러나 나는 여전히 사용 된 변수와 사용되지 않은 변수를 구별 할 수 없다.

나는 실제로 JVM 스택에 액세스하여 어떤 변수가로드되고로드되지 않는 것이 사용되고 있지 않은지 알고있다.

질문은 간단합니다. BCEL을 사용하여 JVM 스택에 액세스하려면 어떻게합니까?

+0

BCEL 또는 ASM을 사용하고 있습니까? –

+0

은 질문에 사용 된 용어에 익숙하지 않지만 이클립스는 이미이 기능을 가지고 있음을주의해야한다. 설정의 경고 범주 안에있다. –

+0

바이트 코드에서 사용되지 않는 변수를 찾으려면 어떻게해야합니까? FindBugs를 사용할 수 있습니다 – Kousalik

답변

1

메소드의 명령리스트를 얻음으로써 바이트 코드에서 사용/사용되지 않은 변수를 감지 할 수 있습니다.

나는 전에이 시도하지 않은, 이것은 전혀 가능하다는 것을 보여주는 실험이다,하지만이보다 더 쉽고 우아한 방법이 희망 :

import org.apache.bcel.Repository; 
import org.apache.bcel.classfile.Constant; 
import org.apache.bcel.classfile.ConstantFieldref; 
import org.apache.bcel.classfile.ConstantNameAndType; 
import org.apache.bcel.classfile.ConstantPool; 
import org.apache.bcel.classfile.JavaClass; 
import org.apache.bcel.classfile.LocalVariable; 
import org.apache.bcel.classfile.LocalVariableTable; 
import org.apache.bcel.classfile.Method; 
import org.apache.bcel.generic.ConstantPoolGen; 
import org.apache.bcel.generic.GETFIELD; 
import org.apache.bcel.generic.Instruction; 
import org.apache.bcel.generic.InstructionHandle; 
import org.apache.bcel.generic.InstructionList; 
import org.apache.bcel.generic.LoadInstruction; 
import org.apache.bcel.generic.LocalVariableInstruction; 
import org.apache.bcel.generic.MethodGen; 

public class UnusedVariablesTest 
{ 
    private int usedInt; 
    private String usedString; 
    private int unusedInt; 
    private String unusedString; 

    public static void main(String[] args) throws ClassNotFoundException 
    { 
     String className = "UnusedVariablesTest"; 
     JavaClass c = Repository.lookupClass(className); 
     ConstantPool cp = c.getConstantPool(); 
     ConstantPoolGen cpg = new ConstantPoolGen(cp); 
     for (Method m : c.getMethods()) 
     { 
      //System.out.println("Method "+m); 
      MethodGen mg = new MethodGen(m, className, cpg); 
      InstructionList il = mg.getInstructionList(); 
      InstructionHandle[] ihs = il.getInstructionHandles(); 
      for(int i=0; i < ihs.length; i++) { 
       InstructionHandle ih = ihs[i]; 
       Instruction instruction = ih.getInstruction(); 
       //System.out.println(" "+instruction); 
       if (instruction instanceof LocalVariableInstruction) 
       { 
        LocalVariableInstruction lvi = (LocalVariableInstruction)instruction; 
        LocalVariableTable lvt = m.getLocalVariableTable(); 
        int index = lvi.getIndex(); 
        LocalVariable lv = lvt.getLocalVariable(index, ih.getPosition()); 
        if (lv != null) 
        { 
         System.out.println("Using "+lv.getName()); 
        } 
       } 
       else if (instruction instanceof GETFIELD) 
       { 
        GETFIELD getfield = (GETFIELD)instruction; 
        int index = getfield.getIndex(); 
        Constant constant = cp.getConstant(index); 
        if (constant instanceof ConstantFieldref) 
        { 
         ConstantFieldref cfr = (ConstantFieldref)constant; 
         Constant constant2 = cp.getConstant(cfr.getNameAndTypeIndex()); 
         if (constant2 instanceof ConstantNameAndType) 
         { 
          ConstantNameAndType cnat = (ConstantNameAndType)constant2; 
          System.out.println("Using "+cnat.getName(cp)); 
         } 
        } 
       } 
      } 
     } 
    } 

    void someMethod(int usedIntArgument, int unusedIntArgument) 
    { 
     System.out.println(usedInt+usedString+usedIntArgument); 
    } 
} 

에서가 사용 된 필드, 인수 및 지역 변수를 최소한 인쇄하여 사용되지 않는 것들을 탐지하는 기초가 될 수 있습니다.

+0

이것은 내게 많은 도움을 주었지만 그렇지 않았습니다. 정적 클래스 멤버 변수를 사용하여 정적 클래스 멤버 변수를 처리하는 명령을 확인하는 세 번째 if 문을 추가해야했습니다. –

+0

@Ali_AUB 네, 앞에서 언급했듯이 이것은 단지 개념 증명 일 뿐이며 (예 : 익명의 내부 클래스와 함께 작동하는지 여부) 확장 될 수 있으며 (언급 한 정적 멤버의 경우) 확장되어야합니다. 그러나 최종 해결책을 찾는 데 도움이된다면이 솔루션을 (자신의 질문에 대한) 답변으로 게시하는 것을 고려해야합니다. 아마도 다른 사람들에게 도움이 될 것입니다. – Marco13