ClassNotFoundException 與 NoClassDefFoundError 到底有什麼區別?

Photo By Instagram sooyaaa

問題 12

你在開發中碰到過 ClassNotFoundException 和 NoClassDefFoundError 嗎?它們有什麼區別?

我的答案

首先這倆個錯誤都代表着 JVM 無法找到相關的類而拋出的錯誤,但是它們發生的場景,以及類型卻截然不同。


類型

從類型上來說 ClassNotFoundException 是 Exception 系的,而 NoClassDefFoundError 是 Error 系的,雖然他們都是 Throwable 的子孫,但是使用場景卻截然不同。

Error 系的錯誤一旦拋出,則代表着這個錯誤是無法修復的,應用程序不應當去捕捉這個錯誤,因爲這個類型的錯誤正常情況下永遠也不會出現。

Exception 系的輕微一點,這種錯誤允許我們在應用程序中處理,是一種可以預知的錯誤。


發生場景

ClassNotFoundException 一般會在我們的應用程序去試圖加載一個類的時候,發現當前類路徑中無法找到該類的 class 文件而拋出的,例如如下幾個方法:

Class 的 forName 方法

ClassLoader 的 findSystemClass 和 loadClass 方法

雖然 NoClassDefFoundError 也是在 JVM 試圖加載一個類的時候發現類不存在然後拋出的錯誤,但是它是在我們使用 new 來實例化一個對象的時候拋出的。

如下我們做了一個小測試,定義了一個 Solution 類,然後在 Main 類中使用它,當 2 個類都編譯完成以後,我們刪除掉 Solution 類的 class 文件,然後運行 Main 類:

 1public class Main {
 2
 3   public static void main(String[] args) throws ClassNotFoundException {
 4       try {
 5           Solution solution = new Solution();
 6      } catch (Throwable e) {
 7           e.printStackTrace();
 8      }
 9
10       try {
11           Class.forName("jvm.Solution");
12      } catch (Exception e) {
13           e.printStackTrace();
14      }
15       System.out.println("over");
16  }
17}
18
19public class Solution {
20}

此時我們會得到如下異常信息:

 1java.lang.NoClassDefFoundError: jvm/Solution
 2       at jvm.Main.main(Main.java:12)
 3Caused by: java.lang.ClassNotFoundException: jvm.Solution
 4       at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
 5       at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
 6       at java.security.AccessController.doPrivileged(Native Method)
 7       at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
 8       at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
 9       at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
10       at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
11      ... 1 more
12java.lang.ClassNotFoundException: jvm.Solution
13       at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
14       at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
15       at java.security.AccessController.doPrivileged(Native Method)
16       at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
17       at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
18       at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)

你會發現,使用 new 來初始化對象時候,拋出來的最外層是 NoClassDefFoundError 錯誤,然而它的底層還是因爲 ClassNotFoundException 異常造成的。而使用 Class.forName 去加載類呢,則會直接拋出 ClassNotFoundException 異常。

如上即爲 ClassNotFoundException 和 NoClassDefFoundError 的區別,你 get 到了嗎?

以上即爲昨天的問題的答案,小夥伴們對這個答案是否滿意呢?歡迎留言和我討論。

又要到年末了,你是不是又悄咪咪的開始看機會啦。爲了廣大小夥伴能充足電量,能順利通過 BAT 的面試官無情三連炮,我特意推出大型刷題節目。每天一道題目,第二天給答案,前一天給小夥伴們獨立思考的機會。

點下“在看”,鼓勵一下?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章