有兩種解決方法:
1.使用visitInsn(int opcode)
方法MethodVisitor
:
//this is the custom method visitor
private class InsertInitCodeBeforeReturnMethodVisitor extends MethodVisitor{
public InsertInitCodeBeforeReturnMethodVisitor(MethodVisitor mv) {
super(Opcodes.ASM4, mv);
}
@Override
public void visitInsn(int opcode) {
//whenever we find a RETURN, we instert the code, here only crazy example code
switch(opcode) {
case Opcodes.IRETURN:
case Opcodes.FRETURN:
case Opcodes.ARETURN:
case Opcodes.LRETURN:
case Opcodes.DRETURN:
case Opcodes.RETURN:
mv.visitVarInsn(Opcodes.ALOAD, 42);
break;
default: // do nothing
}
super.visitInsn(opcode);
}
}
2.使用onMethodExit(int opcode)
方法在AdviceAdapter
在org.objectweb.asm.commons
:
//this is the custom method visitor
private class InsertInitCodeBeforeReturnMethodVisitor extends AdviceAdapter{
public InsertInitCodeBeforeReturnMethodVisitor(MethodVisitor mv, int access, String name, String desc) {
super(Opcodes.ASM4, mv, access, name, desc);
}
@Override
protected void onMethodExit(int opcode) {
if(opcode != Opcdoes.ATHROW) {
mv.visitVarInsn(Opcodes.ALOAD, 42);
}
}
}
我個人喜歡AdviceAdapter更好,因爲它就像你有與第一溶液做去除使得實際調用到原來的返回指令的頭痛(如super.visitInsn(opcode);
)。其次,它提供了一個很好的抽象,專門用於訪問RETURN
指令(和ATHORW
);這在香草MethodVisitor
中的visitInsn(int opcode)
方法中是不正確的,在這種情況下,您必須檢測訪問RETURN
指令,其中包括可能與可能或不可能與手頭問題相關的許多其他指令,如DUP
s,ICONST_0
等。
但是,這又取決於手頭的問題。如果這是正在執行的唯一儀器,我將堅持AdviceAdapter
。如果您還有其他事情要與RETURN
指示一起進行,我可能會留下簡單的MethodVisitor
,因爲它可能會給我更多的靈活性。這就是說,我一直在使用AdviceAdapter
一年多的時間來完成一個重型儀器驅動的項目,到目前爲止它的工作狀況很好!
編輯:
應用方法,遊客
它往往並不清楚如何使用或應用的方法,訪問者/法適配器(至少對我來說) ,所以我在這裏彙總了一個快速代碼示例:gist.github.com/VijayKrishna/1ca807c952187a7d8c4d,它顯示瞭如何通過其相應的類訪問者/類適配器使用方法適配器。在示例代碼片段中,我已經改變了我在這個答案中使用的方法適配器的名稱,但他們也做了同樣的事情。此外,該代碼片段顯示了一個擴展AdviceAdapter
的方法適配器。
總之,你先「調用」之類的適配器如下:
ClassReader cr = new ClassReader(in);
ClassWriter cw = new ClassWriter(ClassReader.EXPAND_FRAMES);
ReturnAdapter returnAdapter = new ReturnAdapter(cw, className);
cr.accept(returnAdapter, 0);
你再跟進調整方法作爲類適配器的visitMethod
方法如下:
MethodVisitor mv;
mv = cv.visitMethod(access, name, desc, signature, exceptions);
mv = new MethodReturnAdapter(Opcodes.ASM4, className, access, name, desc, mv);
return mv;
莫非你提供了一個在方法代碼之前添加代碼的例子嗎? – CamHart 2015-03-17 06:08:32