2013-03-05 1 views
2

Я использую java Instrumentation и ASM ByteCode Library для разработки Javaagent. Как получить исключение Runtime, созданное методом?ASM ByteCode - stackTrace исключения

Прилагается код. Здесь я получаю, закончен ли метод нормально или выбрасывает исключение . Но не удалось получить исключение. Как получить исключение?

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

ответ

2

Вот простой пример. Сначала мы создаем кучу меток для переменных в коде, к которому нам нужно обратиться. Затем мы создаем блок try-catch вокруг выполнения метода. Затем мы вызываем код в блоке «try», и если в блоке try выбрано исключение, выполнение переходит к метке lCatchBlockStart с исключением в стеке. Пример блока catch вызывает e.printStackTrace().

В этом примере я использовал локальную переменную номер 1, потому что она была доступна. Возможно, вам придется выбрать другую переменную - конечно, вы не должны иметь, чтобы сохранить исключение в переменной, но это довольно часто.

Если вы не используете флаг COMPUTE_FRAMES при создании своего ClassWriter, вам также нужно будет вставить вызовы 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); 
+0

Привет, спасибо за вашу помощь .. я прилагаю код, в этом коде, где вставить строки, заданные вами ... –

+0

Так, Допустим, у меня есть ручка начала/конца любой метод, и я могу что-то добавить. Но я хочу распечатать трассировку стека любого исключения, которое вызывается текущим методом или методом, вызываемым из этого текущего метода. Как я получу объект исключения, который вызывается этим методом? – AKS

+0

В моем примере кода строка с 'ASTORE, 1' хранит исключение в локальной переменной 1. Затем вы можете извлечь ее туда столько раз, сколько хотите. В моем примере я загружаю его 'ALOAD, 1' и вызываю' printStackTrace' на нем. –