あなたの試行の説明が正しい方向を指しているため、あなたが直面している実際の障害物は、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
多分あなたの質問があなた自身で問題を解決する努力を示していないので、誰かがdownvote。現在、他の人が仕事をしたいと思っています。これまでに行ったコードを遡って、問題がどこにあるかを明確にしてください。 – SubOptimal
これは私が他のオプションを持っていないときに来る場所です。誰もここに来て、他のオプションが開いていれば詳細な質問をするのをやめようとは思わない。私はここに来る前に私が調べたオプションを置くべきかもしれない。 – AKS