
階段順序:加載 → 驗證 → 準備 → 解析 → 初始化 → 使用 → 卸載。注意:階段啟動順序固定,但執行可交叉(如驗證與準備可並行)。
new 實例化、讀寫靜態欄位(非 final 常數)、呼叫靜態方法Class.forName、Method.invoke)main 方法)MethodHandle 解析為靜態欄位/方法句柄且類未初始化⚠️ final static 基本型別/字串常數編譯期進入常數池,不觸發類初始化。
java.lang.Class 物件,作為方法區資料的存取入口0xCAFEBABE、版本號、常數池合法性int 傳給 long 指令)
僅針對 static 變數(不含實例變數),在方法區分配記憶體並設為零值(非程式碼指定的初始值)。
| 型別 | 零值 |
|---|---|
| int/short/byte | 0 |
| long | 0L |
| float/double | 0.0f/0.0d |
| char | '\u0000' |
| boolean | false |
| reference | null |
針對 7 類符號引用:類/介面、欄位、類方法、介面方法、方法型別、方法句柄、呼叫點限定符。
<clinit>() 與建構子static {} 區塊<clinit>() 先於子類執行;介面無 static {},僅在使用介面常數時初始化父介面<clinit>(),其餘阻塞等待// 執行順序示例:B1 → A1 → B2 → A2 → B2 → A2
class Parent { static { System.out.println("B1"); } Parent() { System.out.println("B2"); } }
class Child extends Parent { static { System.out.println("A1"); } Child() { System.out.println("A2"); } }

| 加載器 | 搜尋範圍 |
|---|---|
| 啟動類加載器 | JAVA_HOME/lib、-Xbootclasspath 指定路徑 |
| 擴充類加載器 | JAVA_HOME/lib/ext、java.ext.dirs |
| 應用程式類加載器 | ClassPath (用戶類別) |
| 自定義類加載器 | 繼承 ClassLoader,覆寫 findClass |
優勢:避免重複載入、保護核心類庫不被竄改(如無法自定義 java.lang.String)、確保類在 JVM 中唯一性(同一類加載器下)。
public class HotSwapClassLoader extends ClassLoader {
private String classPath;
@Override protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] data = loadClassBytes(name); // 從檔案/網路/資料庫讀取位元組碼
return defineClass(name, data, 0, data.length);
}
}
熱部署核心:棄用舊 ClassLoader、建立新 ClassLoader 重新載入更新後的類。舊實例持有舊 Class 參考,新實例使用新 Class,實現無重啟更新。注意:需處理靜態狀態遷移、資源釋放、執行緒安全等問題。
⚠️ 破壞雙親委派:覆寫 loadClass;遵守規範:覆寫 findClass。