2

我正在使用 asm 仪器库。使用 visitVarInsn 我得到一个局部变量的索引。我想使用该索引并接收更多有用的信息,例如变量的名称和类型。你知道怎么做吗?谢谢。

4

2 回答 2

2

我正在使用下面的代码:

    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);
        }
    }
于 2012-06-14T11:43:08.073 回答
0

LocalVariablesSorter.visitLocalVariable方法中选择它。

于 2010-12-01T12:31:04.487 回答