Java中NoClassDefFoundError?和?ClassNotFoundException的區(qū)別
前言:
從類繼承層次上來(lái)看,ClassNotFoundException是從Exception繼承的,所以ClassNotFoundException是一個(gè)檢查異常。NoClassDefFoundError是從Error繼承的。和ClassNotFoundException相比,明顯的一個(gè)區(qū)別是,NoClassDefFoundError并不需要應(yīng)用程序去關(guān)心catch的問(wèn)題。
NoClassDefFoundError
當(dāng)JVM在加載一個(gè)類的時(shí)候,如果這個(gè)類在編譯時(shí)是可用的,但是在運(yùn)行時(shí)找不到這個(gè)類的定義的時(shí)候,JVM就會(huì)拋出一個(gè)NoClassDefFoundError錯(cuò)誤。比如當(dāng)我們?cè)趎ew一個(gè)類的實(shí)例的時(shí)候,如果在運(yùn)行時(shí)類找不到,則會(huì)拋出一個(gè)NoClassDefFoundError的錯(cuò)誤。通常發(fā)生在執(zhí)行動(dòng)態(tài)代碼塊或者初始化靜態(tài)字段時(shí)報(bào)了異常,從而導(dǎo)致類初始化失敗而引發(fā)NoClassDefFoundError。
案例如下:
public class ClassWithInitErrors { static int data = 1 / 0; } public class NoClassDefFoundErrorTest { public ClassWithInitErrors getClassWithInitErrors() { ClassWithInitErrors test = new ClassWithInitErrors(); return test; } @Test(expected = NoClassDefFoundError.class) public void givenInitErrorInClass_whenloadClass_thenNoClassDefFoundError() { NoClassDefFoundErrorTest sample = new NoClassDefFoundErrorTest(); sample.getClassWithInitErrors(); } }
執(zhí)行程序后會(huì)出現(xiàn)如下錯(cuò)誤:
java.lang.Exception: Unexpected exception, expected<java.lang.NoClassDefFoundError> but was<java.lang.ExceptionInInitializerError>
at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:28)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
... more
Caused by: java.lang.ArithmeticException: / by zero
at com.zjq.dailyrecord.throwable.ClassWithInitErrors.<clinit>(ClassWithInitErrors.java:4)
... 25 more
ClassNotFoundException
當(dāng)應(yīng)用程序運(yùn)行的過(guò)程中嘗試使用類加載器去加載Class文件的時(shí)候,如果沒(méi)有在classpath中查找到指定的類,就會(huì)拋出ClassNotFoundException。一般情況下,當(dāng)我們使用Class.forName()或者ClassLoader.loadClass以及使用ClassLoader.findSystemClass()在運(yùn)行時(shí)加載類的時(shí)候,如果類沒(méi)有被找到,那么就會(huì)導(dǎo)致JVM拋出ClassNotFoundException。
最簡(jiǎn)單的,當(dāng)我們使用JDBC去連接數(shù)據(jù)庫(kù)的時(shí)候,我們一般會(huì)使用Class.forName()的方式去加載JDBC的驅(qū)動(dòng),如果我們沒(méi)有將驅(qū)動(dòng)放到應(yīng)用的classpath下,那么會(huì)導(dǎo)致運(yùn)行時(shí)找不到類,所以運(yùn)行Class.forName()會(huì)拋出ClassNotFoundException。
案例如下:
public class ClassNotFoundExceptionTest { public static void main(String[] args) { try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
執(zhí)行后輸出:
java.lang.ClassNotFoundException: com.mysql.jdbc.Driver at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:264) at com.zjq.dailyrecord.throwable.ClassNotFoundExceptionTest.main(ClassNotFoundExceptionTest.java:6)
總結(jié)區(qū)別:
解決辦法
他們的主要原因是運(yùn)行時(shí)類路徑中類文件不可用。
下面是幾點(diǎn)具體的原因:
- 排查所需的jar包是否在類路徑中,如果沒(méi)有就添加進(jìn)去。
- 如果發(fā)現(xiàn)類在classpath里面,很有可能是classpath被重寫了,需要再次確定應(yīng)用準(zhǔn)確的classpath
- 依賴包發(fā)生了沖突,比如應(yīng)該依賴高版本jar包,但又其它包傳遞依賴了低版本jar包,導(dǎo)致高版本中某些類找不到。
- 如果應(yīng)用中用到了多個(gè)類加載器,一個(gè)類加載器加載的類,無(wú)法再其他的類加載器中使用。
到此這篇關(guān)于Java中NoClassDefFoundError 和 ClassNotFoundException的區(qū)別的文章就介紹到這了,更多相關(guān)Java NoClassDefFoundError 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深入淺析springsecurity入門登錄授權(quán)
SpringSecurity為我們提供了基于注解的權(quán)限控制方案,這也是我們項(xiàng)目中主要采用的方式,我們可以使用注解去指定訪問(wèn)對(duì)應(yīng)的資源所需的權(quán)限,這篇文章主要介紹了springsecurity入門登錄授權(quán),需要的朋友可以參考下2024-05-05Kotlin 內(nèi)聯(lián)函數(shù)詳解及實(shí)例
這篇文章主要介紹了Kotlin 內(nèi)聯(lián)函數(shù)詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-06-06Java INPUTSTREAM如何實(shí)現(xiàn)重復(fù)使用
這篇文章主要介紹了Java INPUTSTREAM如何實(shí)現(xiàn)重復(fù)使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10SpringBoot無(wú)法識(shí)別bootstrap.yml小綠葉問(wèn)題的解決辦法
一般單獨(dú)使用?Spring?Boot?時(shí),bootstrap.yml?文件一般是不會(huì)生效的,也就是沒(méi)有小綠葉圖標(biāo),本文給大家介紹了SpringBoot無(wú)法識(shí)別bootstrap.yml小綠葉問(wèn)題的解決辦法,文中給出了兩種解決方案,需要的朋友可以參考下2024-07-07springboot Actuator的指標(biāo)監(jiān)控可視化功能詳解
SpringBoot Actuator是springboot為簡(jiǎn)化我們對(duì)微服務(wù)項(xiàng)目的監(jiān)控功能抽取出來(lái)的模塊,使得我們每個(gè)微服務(wù)快速引用即可獲得生產(chǎn)界別的應(yīng)用監(jiān)控、審計(jì)等功能。這篇文章主要介紹了springboot Actuator的指標(biāo)監(jiān)控可視化,需要的朋友可以參考下2021-08-08Spring MVC數(shù)據(jù)處理和亂碼問(wèn)題詳解
這篇文章主要給大家介紹了關(guān)于Spring MVC數(shù)據(jù)處理和亂碼問(wèn)題的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12如何使用Spring?Boot設(shè)置上傳文件大小限制
上傳文件是互聯(lián)網(wǎng)中常應(yīng)用的場(chǎng)景之一,最典型的情況就是上傳頭像等,下面這篇文章主要給大家介紹了關(guān)于如何使用Spring?Boot設(shè)置上傳文件大小限制的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01Java實(shí)現(xiàn)int、long、Integer、Long之間的相互轉(zhuǎn)換
本文主要介紹了Java實(shí)現(xiàn)int、long、Integer、Long之間的相互轉(zhuǎn)換,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08