目前尚不清楚您所面臨的實際障礙是您的企圖描述是否指向正確的方向visitTryCatchBlock
和visitLabel
。這裏是一個自包含的例子做這項工作:
import java.io.IOException;
import java.lang.reflect.Method;
import org.objectweb.asm.*;
public class EnhanceExceptionHandler {
static class Victim {
public static void hello(boolean doThrow) {
try {
System.out.println("in try");
if(doThrow) {
throw new Exception("just for demonstration");
}
} catch(Exception e){
System.out.println("in catch");
}
}
static void passException(Exception e) {
System.out.println("passException(): "+e);
}
}
public static void main(String[] args)
throws IOException, ReflectiveOperationException {
Class<EnhanceExceptionHandler> outer = EnhanceExceptionHandler.class;
ClassReader classReader=new ClassReader(
outer.getResourceAsStream("EnhanceExceptionHandler$Victim.class"));
ClassWriter classWriter=new ClassWriter(classReader,ClassWriter.COMPUTE_FRAMES);
classReader.accept(new ClassVisitor(Opcodes.ASM5, classWriter) {
private String className;
@Override
public void visit(int version, int access, String name, String signature,
String superName, String[] interfaces) {
className=name;
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
MethodVisitor visitor
= super.visitMethod(access, name, desc, signature, exceptions);
if(name.equals("hello")) {
visitor=new MethodVisitor(Opcodes.ASM5, visitor) {
Label exceptionHandler;
@Override
public void visitLabel(Label label) {
super.visitLabel(label);
if(label==exceptionHandler) {
super.visitInsn(Opcodes.DUP);
super.visitMethodInsn(Opcodes.INVOKESTATIC, className,
"passException", "(Ljava/lang/Exception;)V", false);
}
}
@Override
public void visitTryCatchBlock(
Label start, Label end, Label handler, String type) {
exceptionHandler=handler;
super.visitTryCatchBlock(start, end, handler, type);
}
};
}
return visitor;
}
}, ClassReader.SKIP_FRAMES|ClassReader.SKIP_DEBUG);
byte[] code=classWriter.toByteArray();
Method def=ClassLoader.class.getDeclaredMethod(
"defineClass", String.class, byte[].class, int.class, int.class);
def.setAccessible(true);
Class<?> instrumented=(Class<?>)def.invoke(
outer.getClassLoader(), outer.getName()+"$Victim", code, 0, code.length);
Method hello=instrumented.getMethod("hello", boolean.class);
System.out.println("invoking "+hello+" with false");
hello.invoke(null, false);
System.out.println("invoking "+hello+" with true");
hello.invoke(null, true);
}
}
正如你所看到的,它是直接的,只是記錄異常處理程序的標籤在visitTryCatchBlock
和遇到的visitLabel
代碼位置後立即注入所需的代碼。其餘的是讀取和轉換類文件並加載測試結果的批量代碼。
當您投票回答此問題時,請至少提出意見。 – AKS
也許有人會因爲你的問題沒有表現出努力來解決問題而自鳴得意。目前看起來你更希望別人做你的工作。通過您迄今爲止所做的代碼,並明確您的問題在哪裏。 – SubOptimal
這是我沒有其他選擇的地方。如果有其他選擇是開放的,沒有人願意來到這裏,並努力提出詳細的問題。可能是我應該把我探索之前來到這裏的選項。 – AKS