asm 計測ライブラリを使用しています。visitVarInsn を使用して、ローカル変数のインデックスを取得します。そのインデックスを使用して、変数の名前や型などのより有用な情報を取得したいと考えています。方法はありますか?ありがとう。
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);
}
}
LocalVariablesSorter.visitLocalVariableメソッドで取得します。