[英]Is there a way in Java to intercept the creation of a object by using Instrumentation?
我需要拦截所有 ClassNotFoundException 或 NoClassDefError 的创建:问题是其中一些异常被某些库捕获并在其他异常类型中重新抛出,因此我无法检索类名。 有没有办法通过使用 Intstrumentation 在 Java 中做到这一点?
您可以编写自己的ClassLoader
实现并在loadClass()
或其他可用方法中应用您的逻辑。 ClassLoader
是应用程序中ClassNotFoundException
的常见来源。 除非第 3 方库更改默认类加载过程(例如 OSGI),否则它们仍将调用您的ClassLoader
。
下面的示例向ClassNotFoundException
的构造函数添加检测,并在调用时执行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);
}
}
}
这需要像这样用 META-INF/MANIFEST.MF 编译成 JAR 文件
Manifest-Version: 1.0
Premain-Class: ClassNotFoundExceptionIntercept
Agent-Class: ClassNotFoundExceptionIntercept
Can-Retransform-Classes: true
Can-Redefine-Classes: true
并使用程序参数调用-javaagent:/home/adam/agent-example.jar
这可以证明与吞下异常的测试类一起工作
public class Test {
public static void main(String[] args) {
try {
Class.forName("brexit");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
输出
Constructor invoked
Constructor invoked
Constructor invoked
java.lang.ClassNotFoundException: brexit
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at Test.main(Test.java:9)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.