InsnList没有用于复制自身的方法。

我尝试迭代列表并将每个节点添加到新列表。但是列表的迭代副本执行npe

private static InsnList copy(InsnList insnList) {
        InsnList r = new InsnList();

        for (int i = 0; i < insnList.size(); i++)
            r.add(insnList.get(i));

        return r;
}


InsnList copy = copy(someList);

for (int i = 0; i < copy.size(); i++)
    System.out.println(copy.get(i));


我原本希望复制,但是复制的迭代产生跟随错误

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
    at org.objectweb.asm.tree.InsnList.toArray(InsnList.java:199)
    at org.objectweb.asm.tree.InsnList.get(InsnList.java:110)

最佳答案

尽管我无法重现您的特定例外情况,但这似乎只是您的方法存在基本问题的另一种症状。如the documentation of AbstractInsnNode所述:


  代表字节码指令的节点。一条指令一次最多只能出现一个InsnList


因此,您不能复制InsnList,至少不能通过将相同的节点插入其他列表来复制。这也是add(InsnList)insert(InsnList)InsnList方法从源列表中删除节点的原因。

当您确实想要InsnList的副本时,还必须创建节点对象的副本,这可以通过Visitor API最简单地完成:

private static InsnList copy(InsnList insnList) {
    MethodNode mv = new MethodNode();
    insnList.accept(mv);
    return mv.instructions;
}


但是,只要任务允许,您应该使用ASM的Visitor API将指令直接写入目标类文件,而不是创建指令列表的副本。关于您的实际任务,另请参见this answer

10-07 23:03