为什么静态字段初始化失败会导致NoClassDefFoundError?
这是一个有趣的java问题。
下面的简单 java 程序包含由方法静态初始化的静态字段。实际上,我强制计算 intiailize 值的方法引发 NullPointException,当我访问这样的静态字段时,将引发 NoClassDefFoundError 。看来虚拟机对待这个类不完整。
但是当我访问该类时,它仍然可用;
有谁知道为什么?
class TestClass {
public static TestClass instance = init();
public static TestClass init() {
String a = null;
a.charAt(0); //force a null point exception;
return new TestClass();
}
}
class MainClass {
static public void main(String[] args) {
accessStatic(); // a ExceptionInInitializerError raised cause by NullPointer
accessStatic(); //now a NoClassDefFoundError occurs;
// But the class of TestClass is still available; why?
System.out.println("TestClass.class=" + TestClass.class);
}
static void accessStatic() {
TestClass a;
try {
a = TestClass.instance;
} catch(Throwable e) {
e.printStackTrace();
}
}
}
Here is a interesting java question.
the following simple java program contains static field initialized by a method statically. Actually, I force the method which calculate the intiailize value to raise a NullPointException, When I access such a static field, a NoClassDefFoundError will raised. it seems the VM treat the Class is not complete.
But when I access the Class, it still available;
Does anyone knows why?
class TestClass {
public static TestClass instance = init();
public static TestClass init() {
String a = null;
a.charAt(0); //force a null point exception;
return new TestClass();
}
}
class MainClass {
static public void main(String[] args) {
accessStatic(); // a ExceptionInInitializerError raised cause by NullPointer
accessStatic(); //now a NoClassDefFoundError occurs;
// But the class of TestClass is still available; why?
System.out.println("TestClass.class=" + TestClass.class);
}
static void accessStatic() {
TestClass a;
try {
a = TestClass.instance;
} catch(Throwable e) {
e.printStackTrace();
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
此类问题的答案通常隐藏在规范中的某个位置... (§12.4.2)
初始化类时会发生什么:
步骤 1-4 与此问题有些无关。第 5 步是触发异常的原因:
6-8 继续初始化,8 执行初始化程序,通常发生在步骤 9 中:
但是我们在初始化程序中遇到了错误,因此:
是的,我们看到了空指针异常的
ExceptionInInitializerError
b/c。然后该类被标记为错误,这就是我们第二次从步骤 5 收到异常的原因。
可能是因为
TestClass
仍然存在,它只是被标记为错误。它已经被加载并验证。The answer to such questions is usually buried somewhere in the specs... (§12.4.2)
What happens when classes are initialized:
Steps 1-4 are somewhat unrelated to this question. Step 5 here is what triggers the exception:
6-8 continue the initialization, 8 executes the initializers, and what usually happens is in step 9:
But we got an error in the initializer so:
Yep, we see an
ExceptionInInitializerError
b/c of the null pointer exception.And then the class is marked erroneous which is why we get the exception from step 5 the second time.
Probably because
TestClass
still exists, it's just marked erroneous. It has been already loaded and verified.是的,这通常就是引发
NoClassDefFoundError
的原因。它的名字邪恶,仅此而已。它应该被命名为“类初始化失败异常”或其他名称。由于具有误导性的名称,遇到此错误的 java 程序员浪费了数百人年的时间试图找出找不到该类的原因。
每当看到这个异常时,你应该向上检查日志,并尝试找出类初始化失败的根本原因。
Yes, that's usually why
NoClassDefFoundError
is raised. It's evilly named, that's all. It should've been named as "class init failed exception" or something.Becuase of the misleading name, java programmers who got this error wasted hundreds of man years trying to figure out why the class cannot be found.
Whenever you see this exception, you should check the log upwards, and try to find out the root cause when the class failed to init.
这是正确的...
是的。
类加载器没有尝试删除损坏的类,因为:
要进入这种不一致可见的状态,您的应用程序必须捕获 ClassDefNotFoundError(或超类)并尝试从中恢复。有据可查的事实是,
Error
异常通常是不可恢复的;即,如果您尝试恢复,JVM 可能会处于不一致的状态。这就是这里发生的事情......关于正在加载/初始化的类。That is correct ...
Yes.
The class loader has not tried to remove the broken class because:
To get into a state where this inconsistency is visible, your application has to catch
ClassDefNotFoundError
(or a superclass) and attempted to recover from it. It is a well documented fact thatError
exceptions are generally not recoverable; i.e. if you attempt to recover, the JVM may end up in an inconsistent state. That is what has happened here ... with respect to the classes that were being loaded / initialized.限制
它受到http 的 8.3.2.2 ://psc.informatik.uni-jena.de/languages/Java/javaspec-3.pdf
it is restricted
8.3.2.2 of http://psc.informatik.uni-jena.de/languages/Java/javaspec-3.pdf