ExceptionInInitializerError和NoClassDefFoundError和ClassNotFoundException的区别

好书推荐:Java Web开发实战

ExceptionInInitializerError和NoClassDefFoundError

以前碰到几次NoClassDefFoundError异常,网上都说是因为静态语句块出现异常导致,但是我总是无法通过自己编写得简单事例代码重现(我自己写的代码总是抛出ExceptionInInitializerError,而不是NoClassDefFoundError),直到最近从其他文章看到了一段重现代码才了解了。先看下面可以抛出NoClassDefFoundError异常的代码:

可以看到,Bar和Foot两个写到一个文件Foo.java里面的,所以肯定都在classpath里面,这两个类一定是能找到的。这个代码Bar类的静态属性BAR_ID在类初始化的时候会抛出ArithmeticException异常,导致类初始化失败(不同于对象初始化,即new一个对象,类初始化先于对象初始化)。在第一使用到Bar类时,就会加载并初始化类Bar,抛出的是ExceptionInInitializerError异常导致类加载失败了,当第二次使用一个类加载和初始化失败了的类Bar时,就会抛出NoClassDefFoundError异常了,从上面的代码可以看到除了第一次外,其他几次使用到Bar类时都抛出了NoClassDefFoundError。

其中有意思的是,bar对象的创建失败,导致bar==null,但是仍然可以调用bar的静态方法。

上面的例子是静态属性,下面看一个静态语句块的例子:

其实效果上,静态语句块和静态属性的初始化是一样的。Bar2类第一次加载并初始化失败,就会抛出ExceptionInInitializerError异常。其他时候使用到Bar2类时会抛出NoClassDefFoundError。

ClassNotFoundException

先看段代码:

类ClassNotExist根本不在classpath中,那么就会抛出ClassNotFoundException

总结

尽管jdk里面有注释,但是那也比较难理解,下面整理了下,这三种异常的主要区别

  • ClassNotFoundException:类不在classpath下
  • ExceptionInInitializerError:类在classpath下,类在第一次加载和初始化时静态属性初始化或者静态语句中抛出其他异常,会导致抛出ExceptionInInitializerError异常
  • NoClassDefFoundError:类在classpath下,在类已经加载和初始化过一次,但那次加载和初始化失败了,现在又要使用这个类时就会抛出NoClassDefFoundError异常,其本质原因和ExceptionInInitializerError异常一样,都是因为静态属性初始化或者静态语句块抛出异常导致。

Reference

Why am I getting a NoClassDefFoundError in Java?

 

Post Footer automatically generated by wp-posturl plugin for wordpress.