How to get the return value in asm?

怎甘沉沦 提交于 2019-12-08 13:57:47

问题


I want to extract the return value that type is org.apache.commons.dbcp.BasicDataSource How can I achieve this in asm?

I have to get the instance of the class, org.apache.commons.dbcp.BasicDataSource right after it is created in createDataSource(). So I will visit this method and put some bytecode for getting the return value.


回答1:


I used Advice Adapter to get the return value from a method. A method either return a value or throw exception.Hope below code helps you.

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);
    }
}

}

The line actually gives the return type - mv.visitInsn(Opcodes.DUP); // Return object




回答2:


To get the actual value, you'd need to execute or interpret the bytecode. To change what a method returns, the last two instructions in the method should be:

xload_#
xreturn

where x is the type

 examples:    
//returning an object
aload
areturn

//returning an int
iload
ireturn

and # is the index of the variable in the current frame

The methods you may want to look at are visitBasicVarInstruction/visitVarInstruction (for the load instruction) visitBasicInstruction (for the return instruction)

If you want to go the execution route. In ASM you can create a stub class that contains only the method you want to execute, and the local class fields that method references. Then using the ClassWriter, visit the stub class you created and write it to a file retrieving the bytes.
Then use the URLClassLoader to load that file into the jvm, create an instance of that object and invoke the method via reflection (if you want to create the class at runtime); or write out the file and include in your build path to use it while programming.

The execution option is GREATLY oversimplified, but it is doable (the software I'm writing write now does it). Hopefully I'll be able to opensource it, or at the very least release the binaries publicly.



来源:https://stackoverflow.com/questions/33887368/how-to-get-the-return-value-in-asm

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!