локальные переменные Java - как я могу получить имя или тип переменной, используя ее индекс - PullRequest
2 голосов
/ 01 декабря 2010

Я использую библиотеку инструментов asm. С помощью visitVarInsn я получаю индекс локальной переменной. Я хочу использовать этот индекс и получать более полезную информацию, такую ​​как имя переменная и тип. ты хоть представляешь как? спасибо.

Ответы [ 2 ]

2 голосов
/ 14 июня 2012

Я использую код ниже:

    private LocalVariableNode getLocalVariableNode(VarInsnNode varInsnNode, MethodNode methodNode) {
        int varIdx = varInsnNode.var;
        int instrIdx = getInstrIndex(varInsnNode);
        List<?> localVariables = methodNode.localVariables;
        for (int idx = 0; idx < localVariables.size(); idx++) {
            LocalVariableNode localVariableNode = (LocalVariableNode) localVariables.get(idx);
            if (localVariableNode.index == varIdx) {
                int scopeEndInstrIndex = getInstrIndex(localVariableNode.end);
                if (scopeEndInstrIndex >= instrIdx) {
                    // still valid for current line
                    return localVariableNode;
                }
            }
        }
        throw new RuntimeException("Variable with index " + varIdx + " and scope end >= " + instrIdx
                + " not found for method " + methodNode.name + "!");
    }

Общая проблема заключается в том, что индекс локальной переменной можно использовать повторно. Поэтому вы должны убедиться, что вы получаете правильный LocalVariableNode для данного индекса. Для этого вам нужно убедиться, что данная переменная все еще действительна в той позиции кода, где она используется. Проблема в том, что вы не можете использовать номера строк, потому что

  1. начальная позиция - следующая строка кода после была определена переменная. Поскольку пустые строки и комментарии игнорируются, это может быть любая следующая строка. Но так как код может повторно использовать существующую переменную, это также может быть любая строка перед текущей строкой.

  2. конечная позиция может быть перед начальной позицией по линии (например, в цикле).

  3. код мог быть скомпилирован без информации о строке.

Так что вам нужно использовать указатель инструкций, который всегда верен. Но это внутренняя информация в AbstractInsnNode, к которой нельзя получить доступ извне. Чтобы обойти эту проблему, я использую следующий код, который явно нарушает инкапсуляцию и не рекомендуется по ряду причин. Если ты придумал что-нибудь лучше, дай мне знать! А пока это работает:

    private int getInstrIndex(AbstractInsnNode insnNode) {
        try {
            Field indexField = AbstractInsnNode.class.getDeclaredField("index");
            indexField.setAccessible(true);
            Object indexValue = indexField.get(insnNode);
            return ((Integer) indexValue).intValue();
        } catch (Exception exc) {
            throw new RuntimeException(exc);
        }
    }
0 голосов
/ 01 декабря 2010

Подберите его в методе LocalVariablesSorter.visitLocalVariable .

...