为什么NoClassDefFoundError由静态字段初始化失败引起? [英] Why NoClassDefFoundError caused by static field initialization failure?

查看:217
本文介绍了为什么NoClassDefFoundError由静态字段初始化失败引起?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个有趣的java问题。

Here is a interesting java question.

以下简单java程序包含静态方法初始化的静态字段。实际上,我强制计算intiailize值的方法引发NullPointException,当我访问这样的静态字段时,会引发NoClassDefFoundError。似乎VM对待Class并不完整。

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.

但是当我访问Class时,它仍然可用;

But when I access the Class, it still available;

有谁知道为什么?

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();
        }
    }   
}


推荐答案

这些问题的答案通常都隐藏在规范中...... (§12.4.2)

The answer to such questions is usually buried somewhere in the specs... (§12.4.2)

初始化类时会发生什么:

What happens when classes are initialized:

步骤1-4与此问题有些无关。这里的第5步是触发异常的原因:

Steps 1-4 are somewhat unrelated to this question. Step 5 here is what triggers the exception:


5 如果Class对象处于错误状态,则无法进行初始化。释放Class对象的锁定,抛出NoClassDefFoundError。

5. If the Class object is in an erroneous state, then initialization is not possible. Release the lock on the Class object and throw a NoClassDefFoundError.

6-8继续初始化,8执行初始值设定项,通常在步骤9中执行:

6-8 continue the initialization, 8 executes the initializers, and what usually happens is in step 9:


9 。如果初始化程序的执行正常完成,则锁定此Class对象,将其标记为完全初始化,通知所有等待的线程,释放锁定,并正常完成此过程。

9. If the execution of the initializers completes normally, then lock this Class object, label it fully initialized, notify all waiting threads, release the lock, and complete this procedure normally.

但我们在初始化程序中出错:

But we got an error in the initializer so:


10 否则,初始化器必须通过抛出一些异常E而突然完成。如果E的类不是Error或其子类之一,则创建类ExceptionInInitializerError的新实例,使用E作为参数,并在以下步骤中使用此对象代替E.但是如果由于发生OutOfMemoryError而无法创建新的ExceptionInInitializerError实例,则在下一步中使用OutOfMemoryError对象代替E。

10. Otherwise, the initializers must have completed abruptly by throwing some exception E. If the class of E is not Error or one of its subclasses, then create a new instance of the class ExceptionInInitializerError, with E as the argument, and use this object in place of E in the following step. But if a new instance of ExceptionInInitializerError cannot be created because an OutOfMemoryError occurs, then instead use an OutOfMemoryError object in place of E in the following step.

是的,我们看到 ExceptionInInitializerError b / c的空指针异常。

Yep, we see an ExceptionInInitializerError b/c of the null pointer exception.


11 。锁定Class对象,标记它是错误的,通知所有等待的线程,释放锁定,然后突然完成此过程,原因E或其替换在上一步骤中确定。 (由于某些早期实现中的缺陷,忽略了类初始化期间的异常,而不是如此处所述导致ExceptionInInitializerError。)

11. Lock the Class object, label it erroneous, notify all waiting threads, release the lock, and complete this procedure abruptly with reason E or its replacement as determined in the previous step. (Due to a flaw in some early implementations, a exception during class initialization was ignored, rather than causing an ExceptionInInitializerError as described here.)

然后该类被标记为错误,这就是我们第二次从第5步获得例外的原因。

And then the class is marked erroneous which is why we get the exception from step 5 the second time.


令人惊讶的部分是第三个打印输出,显示 TestClass.class MainClass 中实际持有一个参考到物理 Class 对象。

The surprising part is the third printout which shows that TestClass.class in MainClass actually holds a reference to a physical Class object.

可能是因为 TestClass 仍然存在,它只是标记为错误。它已经加载并验证。

Probably because TestClass still exists, it's just marked erroneous. It has been already loaded and verified.

这篇关于为什么NoClassDefFoundError由静态字段初始化失败引起?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆