我正在使用java Instrumentation和ASM库来开发ByteCode。如何获取方法抛出的运行时异常?
已附上代码。我在这里获取该方法是正常终止还是抛出异常。但是不能检索异常。如何检索异常?
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);
}
}发布于 2013-03-06 04:57:12
这里有一个简单的例子。首先,我们为代码中需要引用的变化点创建一组标签。然后,我们在方法执行过程中设置一个try-catch块。然后,我们调用" try“块中的代码,如果在try块中抛出异常,则执行将跳转到堆栈上具有该异常的lCatchBlockStart标签。示例catch块调用e.printStackTrace()。
我在这个例子中使用了1号局部变量,因为它恰好是可用的。您可能必须选择其他一些变量--当然,您不需要使用来将异常存储在变量中,但是这样做是很常见的。
除非在构造ClassWriter时使用COMPUTE_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);https://stackoverflow.com/questions/15222911
复制相似问题