NoClassDefFoundError的兩種情況

daheww發表於2023-01-12

ClassNotFoundException vs. NoClassDefFoundError

ClassNotFoundException

關於ClassNotFoundException發生的原因,這篇文章ClassNotFoundException vs. NoClassDefFoundError寫得很清晰。

NoClassDefFoundError的兩種情況

總的來說就是:

  • 需要載入的類在classpath中找不到,一般這種情況都是使用類似Class.forName("oracle.jdbc.driver.OracleDriver")的方式獲取類不存在

解決問題的思路:

  • 排查匯入的jar包,對於使用maven的程式來說,就是去檢查pom.xml中的配置
  • 如果配置的有的話就去看一下maven實際匯入的jar包中,對應路徑下是否有這個類
NoClassDefFoundError的兩種情況

NoClassDefFoundError

關於ClassNotFoundException發生的原因,這篇文章ClassNotFoundException vs. NoClassDefFoundError寫得很清晰。

NoClassDefFoundError的兩種情況

總的來說就是:

  • 這個類編譯時有,但是執行時沒有

解決問題的思路:

  • 縮小範圍,確定是哪個類的definition找不到。確定原因後再定解決辦法

以下我演示兩個NoClassDefFoundError的情景。

NoClassDefFoundError的情景

情景1.

B專案依賴了A專案,並配置<optional>為true。

<dependency>
    <groupId>com.example</groupId>
    <artifactId>a</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <optional>true</optional>
</dependency>

C專案依賴了B專案,並呼叫B專案中的某個方法,該方法呼叫了A專案的程式碼。

此時會發生NoClassDefFoundError報錯。

情景2.

  • B專案依賴了A專案
  • C專案依賴了B專案
  • C專案也依賴了A專案

C專案呼叫B專案中的某個方法,該方法呼叫了A專案xxx類的程式碼。

正常來說這個過程是沒問題的,但是B專案、C專案使用的A專案版本不同。
A專案xxx類在這兩個版本的包路徑不同。

這個是我用hutool的過程中發現的一個問題,NetUtil在專案不同版本中包位置不一樣。
NoClassDefFoundError的兩種情況

Note.
需要注意的一點是,如上兩個情景,雖然都是因為少了A專案的程式碼,所以一般堆疊資訊會直接報錯是找不到A專案某個類的definition。
但如果使用A專案的程式碼是在B專案的static塊中(<cinit>方法執行失敗),那麼此時會報的是找不到B專案這個類的definition。

相關文章