我正在使用 asm 仪器库。使用 visitVarInsn 我得到一个局部变量的索引。我想使用该索引并接收更多有用的信息,例如变量的名称和类型。你知道怎么做吗?谢谢。
问问题
1743 次
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。为此,您需要确保给定变量在使用它的代码位置仍然有效。问题是你不能使用行号,因为
开始位置是定义变量后的下一个代码行。由于空行和注释被忽略,因此可以是任何后续行。但由于代码可以重用现有变量,因此也可以是当前行之前的任何行。
结束位置可以在开始位置之前(例如在循环中)。
代码可能在没有行信息的情况下编译。
所以你需要使用指令索引,它总是正确的。但是是 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
于 2010-12-01T12:31:04.487 回答