我需要拦截所有ClassNotFoundException或NoClassDefError的创建:问题在于,其中的某些异常被某些库捕获,并重新抛出为其他异常类型,因此我无法检索类名。Java中是否可以通过使用Intstrumentation来做到这一点?
ClassNotFoundException
这需要使用META-INF / MANIFEST.MF像这样编译成JAR文件
System.err.println
并使用程序参数import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;
import java.security.ProtectionDomain;
import net.bytebuddy.jar.asm.ClassReader;
import net.bytebuddy.jar.asm.ClassVisitor;
import net.bytebuddy.jar.asm.ClassWriter;
import net.bytebuddy.jar.asm.MethodVisitor;
import net.bytebuddy.jar.asm.Opcodes;
public class ClassNotFoundExceptionIntercept {
public static void premain(String agentArgs, Instrumentation inst) throws UnmodifiableClassException {
inst.addTransformer(new ClassFileTransformer() {
@Override
public byte[] transform(ClassLoader l, String name, Class<?> c, ProtectionDomain d, byte[] b)
throws IllegalClassFormatException {
if ("java/lang/ClassNotFoundException".equals(name)) {
return instrument(b);
}
return b;
}
}, true);
inst.retransformClasses(java.lang.ClassNotFoundException.class);
}
private static byte[] instrument(byte[] originalBytes) {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
ClassAdapter adapter = new ClassAdapter(cw);
ClassReader cr = new ClassReader(originalBytes);
cr.accept(adapter, ClassReader.SKIP_FRAMES);
return cw.toByteArray();
}
public static class ClassAdapter extends ClassVisitor implements Opcodes {
public ClassAdapter(ClassVisitor cv) {
super(ASM4, cv);
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature,
String[] exceptions) {
if ("<init>".equals(name)) {
MethodVisitor mv = cv.visitMethod(access, name, descriptor, signature, exceptions);
return new Wrapper(mv);
} else {
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
}
}
private static class Wrapper extends MethodVisitor {
public Wrapper(MethodVisitor mv) {
super(Opcodes.ASM4, mv);
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
mv.visitMethodInsn(opcode, owner, name, desc, itf);
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "err", "Ljava/io/PrintStream;");
mv.visitLdcInsn("Constructor invoked");
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
}
}
}
调用
这可以证明与吞噬异常的测试类一起使用
Manifest-Version: 1.0 Premain-Class: ClassNotFoundExceptionIntercept Agent-Class: ClassNotFoundExceptionIntercept Can-Retransform-Classes: true Can-Redefine-Classes: true
输出
-javaagent:/home/adam/agent-example.jar