Es ist nicht klar, welches tatsächliche Hindernis Sie konfrontiert sind, da Ihre Beschreibung Ihrer Versuche in die richtige Richtung zeigt, visitTryCatchBlock
und visitLabel
. Hier ist ein eigenständiges Beispiel, das die Arbeit erledigt:
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);
}
}
Wie Sie sehen können, ist es geradlinig, notieren Sie nur die Beschriftung des Exception-Handler in den visitTryCatchBlock
und injiziert den gewünschten Code direkt nach der Codeposition in visitLabel
Begegnung . Der Rest ist der Massencode zum Lesen und Transformieren der Klassendatei und zum Laden des Ergebnisses zu Testzwecken.
Bitte geben Sie zumindest einen Kommentar, wenn Sie diese Frage abstimmen. – AKS
Vielleicht jemand Downvote, weil Ihre Frage keine Anstrengung zeigt, das Problem selbst zu lösen. Momentan sieht es so aus, als ob jemand anderes deine Arbeit machen möchte. Hinter den Code, den Sie bisher gemacht haben, und klarstellen, wo Ihr Problem liegt. – SubOptimal
Dies ist der Ort, wo ich komme, wenn ich keine andere Option habe. Niemand möchte hier her kommen und die Mühe machen, die detaillierte Frage zu stellen, wenn andere Möglichkeiten offen sind. Vielleicht sollte ich die Optionen setzen, die ich erforscht habe, bevor ich hierher kam. – AKS