Java asm从方法变量中获取“this”对象

时间:2012-09-03 11:18:05

标签: java java-bytecode-asm invokevirtual

我需要知道调用invokevirtual操作的对象的名称(格式如下:Objectname @ object_id)。是否只能给出MethodInsnNode对象?我知道它与局部变量中的索引0一起存储,但我不知道如何获取它。

2 个答案:

答案 0 :(得分:1)

您需要MethodNode才能访问本地变量。

如果您在变量mn中有关联的MethodNode,并且您的MethodInsnNode存储在insn中,那么:

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
}

答案 1 :(得分:0)

以下是我在JavaFlow库的fork中解决这个难题的方法。 有关具体实现,请查看我的Github存储库中的a CallSiteFinder.java

这个想法如下。当您有方法指令时,您可能会获得正确方法调用所需的必要堆栈大小

Type.getArgumentsAndReturnSizes(methodInsnNode.desc) >> 2

现在按指令列表从反向给定的MethodInsnNode开始移动,并根据遇到的每条指令的OPCode减少获得的堆栈大小。继续,直到你的大小为零。此时,您有一个用于“this”的指令节点 - 实例方法调用的第一个参数。它可能是ALOAD(包括您正在访问的方法 - “ALOD 0”),AALOAD,GETSTATIC,GETFIELD或上一个方法调用的结果,当多个方法调用被链接为

StringBuilder.append(...).append(..)