Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ASM字节码-异常的堆栈跟踪_Java_Assembly_Java Bytecode Asm - Fatal编程技术网

Java ASM字节码-异常的堆栈跟踪

Java ASM字节码-异常的堆栈跟踪,java,assembly,java-bytecode-asm,Java,Assembly,Java Bytecode Asm,我正在使用java指令插入和ASM字节码库来开发Javaagent。 如何获取方法引发的运行时异常 附上代码。这里我得到的是方法是正常终止还是抛出 例外。但无法检索异常。如何检索异常 package com.abc.agent.servlet; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.obje

我正在使用java指令插入和ASM字节码库来开发Javaagent。 如何获取方法引发的运行时异常

附上代码。这里我得到的是方法是正常终止还是抛出 例外。但无法检索异常。如何检索异常

 package com.abc.agent.servlet;

 import org.objectweb.asm.Label;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;

 import com.abc.agent.matcher.HttpServletMethodMatcher;

public class AbcServletMethodVisitorAdapter extends MethodVisitor {
    private String methodName;
    private String className;
    private String description;
    private boolean doMethodMatch;
    private int opcode = -1;

public AbcServletMethodVisitorAdapter(MethodVisitor mv , String  methodName , String description , String className) {
    super(Opcodes.ASM4, mv);
    this.methodName = methodName;
    this.className = className;
    this.description = description;
    this.doMethodMatch = false;
}

public void visitCode() {
    super.visitCode();
    if(methodName.equals("<clinit>") || methodName.equals("<init>"))
        return;
    HttpServletMethodMatcher httpServletMethodMatcher = new HttpServletMethodMatcher(className , methodName , description);
    this.doMethodMatch =  httpServletMethodMatcher.isHttpServletMatch();
    if(this.doMethodMatch){
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitLdcInsn(this.className);
        mv.visitLdcInsn(this.methodName);
        mv.visitLdcInsn(this.description);
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/abc/agent/trace/RootTracer", "httpServletDoMethodBegin", "(Ljava/lang/Object;Ljavax/servlet/http/HttpServletRequest;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
        mv.visitCode();
    }
    else // Other Methods defined in the HttpServlet...
    {
        mv.visitLdcInsn(this.className);
        mv.visitLdcInsn(this.methodName);
        mv.visitLdcInsn(this.description);
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/abc/agent/trace/RootTracer", "httpServletOtherMethodBegin", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
        mv.visitCode();
    }
}

public void visitMaxs(int maxStack, int maxLocals) {
    super.visitMaxs(maxStack + 4, maxLocals);
    }

public void visitInsn(int opcode) {
    if(methodName.equals("<clinit>") || methodName.equals("<init>")){
        // Do nothing....
    }
    else{
        if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) || opcode == Opcodes.ATHROW) {
            this.opcode = opcode;
            mv.visitLdcInsn(this.className);
            mv.visitLdcInsn(this.methodName);
            mv.visitLdcInsn(this.description);
            mv.visitLdcInsn(this.opcode);
            if(this.doMethodMatch) {
                mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/abc/agent/trace/RootTracer", "httpServletDoMethodEnd", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V");
            }
            else{
                mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/abc/agent/trace/RootTracer", "httpServletOtherMethodEnd", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V");
            }
        }
    }
    mv.visitInsn(opcode);
}
}
包com.abc.agent.servlet;
导入org.objectweb.asm.Label;
导入org.objectweb.asm.MethodVisitor;
导入org.objectweb.asm.opcode;
导入org.objectweb.asm.Type;
导入com.abc.agent.matcher.HttpServletMethodMatcher;
公共类AbcServletMethodVisitorAdapter扩展了MethodVisitor{
私有字符串methodName;
私有字符串类名;
私有字符串描述;
私有布尔doMethodMatch;
私有int操作码=-1;
公共AbcServletMethodVisitorAdapter(MethodVisitor mv、字符串methodName、字符串描述、字符串类名){
超级(操作码ASM4,mv);
this.methodName=methodName;
this.className=className;
this.description=描述;
this.doMethodMatch=false;
}
公共无效访问代码(){
super.visitCode();
if(methodName.equals(“”)| methodName.equals(“”)
返回;
HttpServletMethodMatcher HttpServletMethodMatcher=新的HttpServletMethodMatcher(类名、方法名、描述);
this.doMethodMatch=httpServletMethodMatcher.isHttpServletMatch();
如果(此.doMethodMatch){
mv.visitVarInsn(操作码ALOAD,0);
mv.visitVarInsn(操作码ALOAD,1);
mv.visitLdcInsn(this.className);
mv.visitLdcInsn(this.methodName);
mv.visitLdcInsn(本说明);
mv.visitMethodInsn(Opcodes.INVOKESTATIC,“com/abc/agent/trace/RootTracer”,“httpServletDoMethodBegin”,“Ljava/lang/Object;Ljavax/servlet/http/HttpServletRequest;Ljava/lang/String;Ljava/lang/String;)V);
mv.visitCode();
}
else//HttpServlet中定义的其他方法。。。
{
mv.visitLdcInsn(this.className);
mv.visitLdcInsn(this.methodName);
mv.visitLdcInsn(本说明);
mv.visitMethodInsn(Opcodes.INVOKESTATIC,“com/abc/agent/trace/RootTracer”,“httpServletOtherMethodBegin”,“Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V”);
mv.visitCode();
}
}
公共void visitmax(int-maxStack、int-maxLocals){
super.visitMaxs(maxStack+4,maxLocals);
}
公共无效访问号(内部操作码){
if(methodName.equals(“”)| methodName.equals(“”){
//什么也不做。。。。
}
否则{

如果((opcode>=opcode.IRETURN&&opcode,这里是一个简单的示例。首先,我们为需要引用的代码中的可变点创建一组标签。然后,我们围绕方法执行设置一个try-catch块。然后,我们在“try”中调用代码如果在try块中抛出异常,则执行将跳转到lCatchBlockStart标签,堆栈上有异常。示例catch块调用e.printStackTrace()

在本例中,我使用了局部变量1,因为它碰巧可用。您可能必须选择其他变量-当然您没有将异常存储在变量中,但这样做是很常见的

除非在构造ClassWriter时使用COMPUTE\u FRAMES标志,否则还必须插入visitFrame()调用

Label lTryBlockStart = new Label();
Label lTryBlockEnd = new Label();
Label lCatchBlockStart = new Label();
Label lCatchBlockEnd = new Label();
// set up try-catch block for RuntimeException
mv.visitTryCatchBlock(lTryBlockStart, lTryBlockEnd, lCatchBlockStart, "java/lang/RuntimeException");
mv.visitLabel(lTryBlockStart);
// code to call the method goes here
mv.visitLabel(lTryBlockEnd);
mv.visitJumpInsn(GOTO, lCatchBlockEnd); // when here, no exception was thrown, so skip exception handler

// exception handler starts here, with RuntimeException stored on the stack
mv.visitLabel(lCatchBlockStart);
mv.visitVarInsn(ASTORE, 1); // store the RuntimeException in local variable 1
// here we could for example do e.printStackTrace()
mv.visitVarInsn(ALOAD, 1); // load it
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/RuntimeException", "printStackTrace", "()V");

// exception handler ends here:
mv.visitLabel(lCatchBlockEnd);

您好,谢谢您的帮助..我已经附加了代码,在这段代码中,在哪里插入您给出的行…所以,假设我已经获得了任何方法的开始/结束的句柄,我可以在那里添加一些东西。但是我想打印当前方法引发的任何异常或从当前方法调用的方法的堆栈跟踪。我如何获得e此方法引发的exception对象?在我的示例代码中,带有
ASTORE,1
的行将异常存储在局部变量1中。然后您可以从该行中检索任意次数。在我的示例中,我将其加载为
ALOAD,1
,并在其上调用
printStackTrace
。Joans,此代码应插入何处?我想为特定方法的方法体添加这段代码。我应该重写MethodVisitor的visitMethodInsn并调用//代码来调用该方法吗?这里是mv.visitMethodInsn(INVOKESTATIC、mClassName、mMethodName、desc、false);?为什么要将异常存储在索引1中?如果我试图在其中添加此try catch的方法没有任何参数,并且是静态方法,那么在这种情况下,异常将存储在索引0中?