今天我花了一个下午的时间来分析 NoClassDefFoundError。一次又一次验证类路径后,发现有一个类的静态成员抛出了第一次被忽略的异常。之后,每次使用该类都会抛出 NoClassDefFoundError ,而没有有意义的堆栈跟踪:
Exception in thread "main" java.lang.NoClassDefFoundError:
Could not initialize class InitializationProblem$A
at InitializationProblem.main(InitializationProblem.java:19)
就这样。不再需要排队。
归根结底,这就是问题所在:
public class InitializationProblem {
public static class A {
static int foo = 1 / 0;
static String getId() {
return "42";
}
}
public static void main( String[] args ) {
try {
new A();
}
catch( Error e ) {
// ignore the initialization error
}
// here an Error is being thrown again,
// without any hint what is going wrong.
A.getId();
}
}
为了让它不那么容易,除了最后一个电话A.getId()
隐藏在一个非常大的项目的初始化代码中的某个地方。
问题:
现在我经过几个小时的反复试验发现了这个错误,我想知道是否有一种直接的方法可以从抛出的异常开始找到这个错误。关于如何做到这一点有什么想法吗?
我希望这个问题能为其他分析一个无法解释的问题的人提供一个提示NoClassDefFoundError
.
实际上,您永远不应该捕获错误,但您可以通过以下方法找到可能出现的初始化程序问题。
这是一个代理,它将使所有 ExceptionInInitializerError 在创建时打印堆栈跟踪:
import java.lang.instrument.*;
import javassist.*;
import java.io.*;
import java.security.*;
public class InitializerLoggingAgent implements ClassFileTransformer {
public static void premain(String agentArgs, Instrumentation inst) {
inst.addTransformer(new InitializerLoggingAgent(), true);
}
private final ClassPool pool = new ClassPool(true);
public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
try {
if (className.equals("java/lang/ExceptionInInitializerError")) {
CtClass klass = pool.makeClass(new ByteArrayInputStream(classfileBuffer));
CtConstructor[] ctors = klass.getConstructors();
for (int i = 0; i < ctors.length; i++) {
ctors[i].insertAfter("this.printStackTrace();");
}
return klass.toBytecode();
} else {
return null;
}
} catch (Throwable t) {
return null;
}
}
}
它使用 javassist 来修改类。编译并将其放入包含 javassist 类和以下 MANIFEST.MF 的 jar 文件中
Manifest-Version: 1.0
Premain-Class: InitializerLoggingAgent
运行您的应用程序java -javaagent:agentjar.jar MainClass
即使捕获了每个 ExceptionInInitializerError 也会被打印。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)