如何在asm中获取返回值?

时间:2015-11-24 07:05:28

标签: java-bytecode-asm bytecode-manipulation

我想提取类型为org.apache.commons.dbcp.BasicDataSource的返回值如何在asm中实现此目的?

我必须在createDataSource()中创建类的实例org.apache.commons.dbcp.BasicDataSource。所以我将访问此方法并输入一些字节码来获取返回值。

2 个答案:

答案 0 :(得分:1)

我使用Advice Adapter从方法中获取返回值。一个方法返回一个值或抛出异常。希望下面的代码可以帮助你。

import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.AdviceAdapter;

public class MyMethodVisitor extends AdviceAdapter{

Label startFinally = new Label();

public MyMethodVisitor(int access , MethodVisitor mv , String methodName, String description, String className) {
    super(Opcodes.ASM5 , mv, access, methodName, description);
}

public void visitCode() {
    super.visitCode(); 
    mv.visitLabel(startFinally);
}

public void visitMaxs(int maxStack, int maxLocals) {
    Label endFinally = new Label();
    mv.visitTryCatchBlock(startFinally, endFinally, endFinally, null);
    mv.visitLabel(endFinally);
    onFinally(Opcodes.ATHROW);
    mv.visitInsn(Opcodes.ATHROW);
    super.visitMaxs(maxStack, maxLocals);
}

protected void onMethodEnter(){
    // If required, add some code when a method begin
}

protected void onMethodExit(int opcode){
    if(opcode!=ATHROW) {
        onFinally(opcode);
    }
}

private void onFinally(int opcode) {
    if(opcode == Opcodes.ATHROW){
        mv.visitInsn(Opcodes.DUP); // Exception thrown by the method
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "abc/xyz/CatchError", "recordException", "(Ljava/lang/Object)V", false);
    }
    else{
        mv.visitInsn(Opcodes.DUP); // Return object
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "abc/xyz/CatchError", "getReturnObject", "(Ljava/lang/Object)V", false);
    }
}

}

该行实际上给出了返回类型 - mv.visitInsn(Opcodes.DUP); //返回对象

答案 1 :(得分:0)

要获得实际值,您需要执行或解释字节码。要更改方法返回的内容,方法中的最后两条指令应为:

xload_#
xreturn

其中x是类型

 examples:    
//returning an object
aload
areturn

//returning an int
iload
ireturn

和#是当前帧中变量的索引

您可能要查看的方法是visitBasicVarInstruction / visitVarInstruction(用于加载指令)visitBasicInstruction(用于返回指令)

如果你想去执行路线。在ASM中,您可以创建一个存根类,该类仅包含要执行的方法,以及方法引用的本地类字段。然后使用ClassWriter,访问您创建的存根类,并将其写入检索字节的文件 然后使用URLClassLoader将该文件加载到jvm中,创建该对象的实例并通过反射调用该方法(如果要在运行时创建该类);或写出文件并包含在构建路径中以便在编程时使用它。

执行选项极其简单,但它是可行的(我现在正在写的软件就是这样做的)。希望我能够开源它,或者至少公开发布二进制文件。