java - 识别 Java 代码中未使用的变量

标签 java bcel

我需要识别 Java 代码中未使用的未使用变量(参数、局部变量、类成员变量)。基本上我必须使用 BCEL 来访问字节代码并达到我的目标。

我已经成功地使用 ClassGen 来获取所有被调用的方法,然后通过使用 MethodGen 我成功地获取了所有局部变量和函数参数。但是我仍然无法区分已使用和未使用的变量。

我猜我必须访问 JVM 堆栈才能查看实际加载的变量以及未加载的变量。

所以问题很简单: 如何使用 BCEL 访问 JVM 堆栈?

最佳答案

通过获取方法的指令列表,可以从字节码中检测出使用/未使用的变量。

我以前没有尝试过,这只是一个实验,表明它是可能的,但我希望有一种比这更简单、更优雅的方法:

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);
    }
}

至少它打印了使用的字段、参数和局部变量,这可以作为检测未使用的的基础。

关于java - 识别 Java 代码中未使用的变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22236011/

相关文章:

java - 如何使用 JSP 实现此模式

java - 如何消除原始类型并不使用局部变量

java - 无法看到 BCEL 所做的更改

使用 BCEL 的 Java 类修改顺序

java - 如何获取cglib代理类实例的字节码?

java - Realm 对象类 setter 中的枚举支持和自定义逻辑

java - 在基于java的插件中创建gradle任务

java - 字节码:LOOKUPSWITCH 和 TABLESWITCH

java - 我可以在 URL 路径中使用顶级域名吗?

java - IZpack java条件调试(IZpack 4)