我想提取类型为org.apache.commons.dbcp.BasicDataSource的返回值如何在asm中实现此目的?
我必须在createDataSource()中创建类的实例org.apache.commons.dbcp.BasicDataSource。所以我将访问此方法并输入一些字节码来获取返回值。
答案 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中,创建该对象的实例并通过反射调用该方法(如果要在运行时创建该类);或写出文件并包含在构建路径中以便在编程时使用它。
执行选项极其简单,但它是可行的(我现在正在写的软件就是这样做的)。希望我能够开源它,或者至少公开发布二进制文件。