我需要知道调用invokevirtual操作的对象的名称(格式如下-Objectname@object_id)。只给定MethodInsNode对象是否可能?我知道它与索引0一起存储在局部变量中,但我不知道如何获得它。
您需要MethodNode来访问本地变量。
如果变量mn
中有关联的MethodNode,并且在insn
中存储了MethodInsNo,则:
InsnList insnList = mn.instructions;
int instructionIdx = insnList.indexOf(insn);
String name = null;
int wantedLocalVariableIndex = 0;
for (LocalVariableNode lvn : mn.localVariables) {
if (lvn.index == wantedLocalVariableIndex && insnList.indexOf(lvn.start) < instructionIdx && instructionIdx < insnList.indexOf(lvn.end)) {
name = lvn.name;
break;
}
}
if (name != null) {
// we found it's name
}
以下是我如何在JavaFlow库的分叉中解决这个难题的。要了解确切的实现,请查看我的Github存储库中的CallSiteFinder.java。
想法如下。当您有方法指令时,您可能会获得正确方法调用所需的必要堆栈大小
Type.getArgumentsAndReturnSizes(methodInsnNode.desc) >> 2
现在按指令列表从给定的MethodInsNode开始反向移动,并根据遇到的每条指令的OPCode减小获得的堆栈大小。继续,直到你的尺码为零。此时,您有一个用于"this"的指令节点——实例方法调用的第一个参数。它可能是ALOAD(包括您正在访问的方法——"ALOD 0")、AALOAD、GETSTATIC、GETFIELD,或者当几个方法调用像一样被链接时,上一个方法调用的结果
StringBuilder.append(...).append(..)