| 異常 | 觸發階段 | 核心原因 |
|---|---|---|
| NoClassDefFoundError | **運行時** 類加載/鏈接 | 編譯時存在,運行時類定義不可用 |
| ClassNotFoundException | 編譯時/反射加載 | 類路徑中找不到類文件 |
NoClassDefFoundError 是 `LinkageError` 子類,**嚴重錯誤**,通常不可恢復。發生時機:JVM 嘗試加載類(new、靜態字段訪問、方法調用、反射)但類定義缺失或初始化失敗。
class User {
private static String USER_ID = getUserId(); // 靜態字段初始化
private static String getUserId() {
throw new RuntimeException("配置缺失"); // 拋異常
}
}
// 其他類首次使用 User 時
List users = new ArrayList<>();
// 拋出:NoClassDefFoundError: Could not initialize class User
// 日誌中必有:ExceptionInInitializerError
**鐵律**:見 `NoClassDefFoundError` 必查日誌是否有 `ExceptionInInitializerError`。
Exception in thread "main" java.lang.NoClassDefFoundError: com/example/User
at com.example.Main.main(Main.java:10)
Caused by: java.lang.ExceptionInInitializerError
at com.example.User.(User.java:8)
Caused by: java.lang.RuntimeException: 配置缺失
關鍵信息:缺失類全名、觸發位置、根因異常。
System.out.println(System.getProperty("java.class.path"));
// 或啟動參數 -verbose:class 觀察類加載軌跡
# 檢查 JAR 內是否包含
jar -tf your-app.jar | grep User.class
# 檢查文件系統
find /deploy/path -name "User.class"
// 運行時打印類加載器
User.class.getClassLoader()
// 對比不同上下文的加載器
Thread.currentThread().getContextClassLoader()
java -cp "正确的完整classpath" com.example.Main
// 如果正常 → 原啟動腳本/環境污染了 classpath
| 場景 | 解決方案 |
|---|---|
| Maven 依賴 scope=provided | 改為 compile、或運行環境手動添加 JAR |
| 靜態初始化異常 | try-catch 降級、延遲初始化、@PostConstruct |
| 原生庫缺失 | -Djava.library.path=/path/to/libs、JAR 內釋放 |
| 多類加載器衝突 | 統一類加載器、父優先/子優先策略調整、模塊化 |
| 啟動腳本覆蓋 CLASSPATH | 修正腳本、使用 Manifest Class-Path、Fat JAR |
| JDK 安裝損壞 (com.sun.tools.javac.Main) | 重新安裝 JDK、配置 JAVA_HOME/PATH |