blog地址:https://tech101.cn/2018/06/23/ClassNotFoundException_vs_NoClassDefFoundError
在寫Java程序的時候,當一個類找不到的時候,JVM有時候會拋出ClassNotFoundException異常,而有時候又會拋出NoClassDefFoundError。看兩個異常的字面意思,好像都是類找不到,但是JVM為什么要用兩個異常去區分類找不到的情況呢?這個兩個異常有什么不同的地方呢?
ClassNotFoundException
ClassNotFoundException是一個檢查異常。從類繼承層次上來看,ClassNotFoundException是從Exception繼承的,所以ClassNotFoundException是一個檢查異常。
當應用程序運行的過程中嘗試使用類加載器去加載Class文件的時候,如果沒有在classpath中查找到指定的類,就會拋出ClassNotFoundException。一般情況下,當我們使用Class.forName()或者ClassLoader.loadClass以及使用ClassLoader.findSystemClass()在運行時加載類的時候,如果類沒有被找到,那么就會導致JVM拋出ClassNotFoundException。
最簡單的,當我們使用JDBC去連接數據庫的時候,我們一般會使用Class.forName()的方式去加載JDBC的驅動,如果我們沒有將驅動放到應用的classpath下,那么會導致運行時找不到類,所以運行Class.forName()會拋出ClassNotFoundException。
public class MainClass { public static void main(String[] args) { try { Class.forName("oracle.jdbc.driver.OracleDriver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
輸出:
java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:264) at MainClass.main(MainClass.java:7)
NoClassDefFoundError
NoClassDefFoundError異常,看命名后綴是一個Error。從類繼承層次上看,NoClassDefFoundError是從Error繼承的。和ClassNotFoundException相比,明顯的一個區別是,NoClassDefFoundError並不需要應用程序去關心catch的問題。
當JVM在加載一個類的時候,如果這個類在編譯時是可用的,但是在運行時找不到這個類的定義的時候,JVM就會拋出一個NoClassDefFoundError錯誤。比如當我們在new一個類的實例的時候,如果在運行是類找不到,則會拋出一個NoClassDefFoundError的錯誤。
public class TempClass { } public class MainClass { public static void main(String[] args) { TempClass t = new TempClass(); } }
首先這里我們先創建一個TempClass,然后編譯以后,將TempClass生產的TempClass.class文件刪除,然后執行程序,輸出:
Exception in thread "main" java.lang.NoClassDefFoundError: TempClass at MainClass.main(MainClass.java:6) Caused by: java.lang.ClassNotFoundException: TempClass at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 1 more
總結一下區別
ClassNotFoundException | NoClassDefFoundError |
從java.lang.Exception繼承,是一個Exception類型 | 從java.lang.Error繼承,是一個Error類型 |
當動態加載Class的時候找不到類會拋出該異常 | 當編譯成功以后執行過程中Class找不到導致拋出該錯誤 |
一般在執行Class.forName()、ClassLoader.loadClass()或ClassLoader.findSystemClass()的時候拋出 | 由JVM的運行時系統拋出 |