Есть ли способ определить переменные, используемые в методе Java? - PullRequest
3 голосов
/ 18 марта 2012

Есть ли способ определить переменные, используемые конкретным методом Java?

Например, если у меня есть следующий метод:

public void getResult(){
   int result = value1 + value2;
}

Тогда мне нужен список, содержащий имена result, value1 и value2.

Ответы [ 2 ]

4 голосов
/ 18 марта 2012

Это зависит от того, включена ли отладочная информация при компиляции. Если нет, он отбрасывает имена переменных, и на них просто ссылается их адрес стека. Обычно вы предоставляете компилятору опцию «-g», но если вы используете maven, проверьте документацию, чтобы убедиться, что он включен.

Если включена отладка, вы можете использовать такую ​​библиотеку, как BCEL, чтобы узнать эту информацию:

java.lang.reflect.Method javaMethod = ...; // lookup the actual method using reflection
org.apache.bcel.classfile.JavaClassjc = org.apache.bcel.Repository.lookupClass(classname);
org.apache.bcel.classfile.Method method = jc.getMethod(javaMethod);
org.apache.bcel.classfile.LocalVariableTable lvt = method.getLocalVariableTable();

Оттуда у LocalVariableTable есть множество методов для получения списка локальных переменных (см. Документацию bcel).

Есть несколько пакетов, которые могут это сделать, но BCEL и Javassist приходят мне на ум.

4 голосов
/ 18 марта 2012

Вы можете сделать это, только если вы анализируете сгенерированный байт-код.Вы можете использовать библиотеку разработки байт-кода, например, ASM, Javassist и т. Д.

Поскольку, насколько я понимаю, ваш пример использует поле объекта, здесь пример кода использует Javassist и печатает все поля, используемые методами данного класса:

ClassFile cf = new ClassFile(new DataInputStream(className + ".class")));
for (Object m : cf.getMethods()) {
    MethodInfo minfo = (MethodInfo)m;
    CodeAttribute ca = minfo.getCodeAttribute();
    for (CodeIterator ci = ca.iterator(); ci.hasNext();) {
        int index = ci.next();
        int op = ci.byteAt(index);
        if (op == Opcode.GETYFIELD) {
                    int a1 = ci.s16bitAt(index + 1);
                    String fieldName = " " + cf.getConstPool().getFieldrefName(a1); 
            System.out.println("field name: " + fieldName);
        }
    }

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...