ASM。正确克隆JumpInsnNode

时间:2015-01-08 15:12:02

标签: java bytecode java-bytecode-asm

您是否知道如何正确克隆JumpInsnNode?

我尝试了几件事:

1. endList.add(insn.clone(labelNodes));

insn是JumpInsnNode; labelNodes - 方法中的所有labelNodes。 由于从AbsractInsnNode类调用clone方法的clone方法的实现,此代码抛出NullPointerException:

static LabelNode clone(final LabelNode label, final Map<LabelNode, LabelNode> map) {
        return map.get(label);
    }

此方法返回null。

  1. endList.add(new JumpInsnNode(insn.getOpcode(), new LabelNode(insn.label.getLabel())));
  2. 它抛出异常:

    java.lang.ArrayIndexOutOfBoundsException: 0
        at org.objectweb.asm.Frame.a(Unknown Source)
        at org.objectweb.asm.Frame.a(Unknown Source)
        at org.objectweb.asm.MethodWriter.visitMaxs(Unknown Source)
        at org.objectweb.asm.tree.MethodNode.accept(Unknown Source)
        at org.objectweb.asm.tree.MethodNode.accept(Unknown Source)
        at org.objectweb.asm.tree.ClassNode.accept(Unknown Source)
        at com.smartbear.real.agent.Agent.transform(Agent.java:221)
        at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
        at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:424)
        at sun.instrument.InstrumentationImpl.redefineClasses0(Native Method)
        at sun.instrument.InstrumentationImpl.redefineClasses(InstrumentationImpl.java:170)
        at com.smartbear.real.agent.Agent.agentmain(Agent.java:118)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:382)
        at sun.instrument.InstrumentationImpl.loadClassAndCallAgentmain(InstrumentationImpl.java:407)
    

    推理:我需要能够再次加载方法返回值。我能用其他类型的指令做到这一点。但是这种类型的指令:return (test != null);现在对我不起作用。字节代码:

      LINENUMBER 112 L2
        ALOAD 3: tr
        IFNULL L3
        ICONST_1
        IRETURN
       L3
       FRAME APPEND [Boolean]
        ICONST_0
        IRETURN
    

1 个答案:

答案 0 :(得分:2)

您似乎使用了错误的方法。你不应该克隆任意指令来复制返回值,这不仅会变得不必要地复杂,它还可能复制副作用,从而产生与没有Instrumentation不同的意外行为。

复制值,一个方法即将返回,更简单。在执行其中一个…RETURN指令之前,操作数堆栈上必须有实际的返回值。因此,您需要做的就是在DUP指令之前插入适当的DUP指令(DUP2…RETURN)以复制值。然后,您可以插入使用该重复值的日志记录代码。

E.g。您可以将IRETURN的出现更改为:

DUP
INVOKESTATIC java/lang/Integer valueOf (I)Ljava/lang/Integer;
INVOKESTATIC MyLogger logReturnValue (Ljava/lang/Object;)V
IRETURN // the original return instruction

DRETURN

DUP2
INVOKESTATIC java/lang/Double valueOf (D)Ljava/lang/Double;
INVOKESTATIC MyLogger logReturnValue (Ljava/lang/Object;)V
DRETURN // the original return instruction

ARETURN

DUP
INVOKESTATIC MyLogger logReturnValue (Ljava/lang/Object;)V
ARETURN // the original return instruction