ClassNotFoundException和NoClassDefFoundError的區別:
ClassNotFoundException:
- 它是Exception,不是Error在Throwable體系中只是一個Exception,說明它是可恢復的
- 發生的時機
- 當應用試圖通過給定的name加載對應的class時可能拋出此異常,找不到對應的class文件時拋出
- Class.forName(name);
- ClassLoader.findSystemClass();
- ClassLoader.loadClass();
- 當應用試圖通過給定的name加載對應的class時可能拋出此異常,找不到對應的class文件時拋出
NoClassDefFoundException
- Error級別,比Exception要嚴重
- JVM或者ClassLoader試圖加載一個class的definition的時候,找不到對應的class的definition,通常時new A()的時候
因此,當源文件編譯成功,但是運行時找不到需要的class文件時,會出現NoClassDefFoundError。這可能會發生在一個分布式或者生產的JAR中,里面沒有包含所有的需要的class文件。
一個預期編譯時期沒問題的程序在不能運行可能是由于class文件找不到或者和編譯期生成或者面臨的不相同。這是一個非常嚴重的錯誤,程序不能被JVM啟動。
當對應的class文件不能被類加載器找到的時候會拋出ClassNotFoundException,通常情況class在class path下找不到,也有可能是這個class試圖被父類加載器加載的一個class加載,但是這個class只對子類加載器可見。這種情況通常出現在比較復雜的環境中。
人們經常搞混NoClassDefFoundError和ClassNotFoundExcepion,然后兩者大不相同。
java.lang.NoClassDefFoundError:
org/apache/activemq/ActiveMQConnectionFactory
這并不意味著ActiveMQConnectionFactory的class文件在classpath下找不到。實際上恰恰相反,這意味ActiveMQConnectionFactory的class是可以被類加載器找到的,但是在試圖加載這個類的時候,讀取class的definition時出現了錯誤。一般情況下當class中有靜態代碼庫或者靜態字段時,而這些靜態代碼使用了當前類加載器找不到的class時,會出現這樣的問題。因此為了找到罪魁禍首,查看問題中class的源碼,找其中用到的靜態代碼塊和靜態字段,如果不能訪問源碼,試圖反編譯它。
代碼舉例,下面這行代碼,確保SomeClass的class在classpath中。
private static SomeClass foo = new SomeClass();
代碼地址見此處