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 的面試官無情三連炮,我特意推出大型刷題節目。每天一道題目,第二天給答案,前一天給小夥伴們獨立思考的機會。
點下“在看”,鼓勵一下?