【发布时间】:2011-01-13 17:18:00
【问题描述】:
今天我花了一个下午分析 NoClassDefFoundError。一次又一次地验证classpath,结果发现有一个类的静态成员抛出了第一次被忽略的异常。之后,每次使用该类都会抛出一个没有有意义的堆栈跟踪的 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的人来说是一个提示。
【问题讨论】:
-
我的第一个想法是不要抓住和忽略
Errors。永远。 -
这是从文件系统收集的一些测试类的初始化。我试图实例化每个类以查看它是否与给定接口匹配......有些类无法实例化,例如抽象的。所以我抓住了所有的错误并忽略了它们。
-
至少,打印堆栈跟踪。一个空的 catch 块对你来说应该是一个危险信号。 (你用过 FindBugs 吗?它会比你自己更早地捕捉到很多东西。)
-
@tangens 你不需要实例化一个类来查看它是否实现了一个接口。要查看
Class<?> someUnknownClass是否实现了某个接口 IInterface,请执行IInterface.class.isAssignableFrom(someUnknownClass) -
@geoff-reedy:实际上,我做了一个 Class.forName(),甚至这会导致错误。现在我正在寻找更好的方法,请参阅stackoverflow.com/questions/2210930/…
标签: java debugging noclassdeffounderror