Java 憑藉「一次編寫、到處執行」的跨平台能力、自動記憶體管理與安全沙箱模型,成為企業級開發基石。本文系統拆解 JVM 架構、垃圾回收演進、類別載入驗證機制、執行時資料區,構建完整的 Java 運作心智模型。
JVM 是軟體模擬的計算機,屏蔽底層硬體 (x86, ARM, SPARC...) 與作業系統 (Windows, Linux, macOS...) 差異,統一執行 .class 字節碼。Java 原始碼 → javac 編譯 → .class → JVM 解釋/即時編譯 (JIT) → 機器碼執行。
| 組件 | 功能 | 關鍵細節 |
|---|---|---|
| 類別載入器 | 載入 .class 進入方法區 |
雙親委派模型、自定義載入器隔離命名空間 |
| 字節碼驗證器 | 檢查字節碼合法性、類型安全 | 四階段驗證:文件格式、元資料、字節碼、符號引用 |
| 解釋器 | 逐條執行字節碼 | 配合 JIT 編譯器 (C1/C2/Graal) 熱點代碼編譯為機器碼 |
| 指令集 | 基於棧的字節碼指令 | 操作碼 1 byte,最多 256 種指令;操作數長度可變 |
| 執行引擎運行時區 | 棧幀、局部變數表、操作數棧、程序計數器 | 每條執行緒私有;支援遞迴、異常回溯 |
| 垃圾回收器 (GC) | 自動回收堆中無用物件 | 分代收集 (新生代/老年代)、G1/ZGC/Shenandoah 低延遲演算法 |
早期 Applet 時代核心:限制程式只能在受控記憶體區域執行,禁止訪問本地檔案系統、網路、系統屬性。雖然 Applet 已退役,但沙箱思想延伸為現代 SecurityManager、模組系統 (JPMS) 的強封裝、容器級隔離 (Docker/gVisor)。
ClassLoader 讀取二進制流 → 生成 java.lang.Class 物件放入方法區。<clinit>() (靜態區塊、靜態變數賦值)。關鍵:驗證器確保型別安全、存取控制、呼叫慣例,阻擋惡意字節碼 (如偽造存取私有欄位、棧溢位、非法跳轉)。
+--------------------------+
| Heap (共享) | <- 物件實例、陣列、字串常量池 (JDK7+ 移入堆)
| 新生代 | 老年代 | GC 主戰場
+--------------------------+
| Method Area (共享) | <- 類別元資料、常量池、靜態變數、JIT 編譯代碼
| (Metaspace JDK8+) |
+--------------------------+
| Java Stack (執行緒私有) | <- 棧幀 (局部變數表、操作數棧、動態連結、返回地址)
| Native Stack (執行緒私有)|
| PC Register (執行緒私有) |
+--------------------------+
StrongReference > SoftReference (記憶體不足才回收) > WeakReference (下次 GC 回收) > PhantomReference (追蹤回收時機)
| 時代 | 代表收集器 | 特點 |
|---|---|---|
| JDK 1.3-1.4 | Serial / Parallel Scavenge | 單執行緒/多執行緒、Stop-The-World、新生代複製+老年代標記整理 |
| JDK 1.5-1.7 | CMS (Concurrent Mark Sweep) | 老年代低延遲、並發標記/清除、碎片整理需 Full GC、對 CPU 敏感 |
| JDK 1.7+ | G1 (Garbage First) | Region 分區、混合收集、可預測停頓、逐漸取代 CMS |
| JDK 11+ | ZGC / Shenandoah | 亞毫秒級停頓、着色指標/連接矩陣、超大堆 (TB 級) 適用 |
JVM 以字節碼中立格式、自動記憶體管理、多層次安全驗證三大支柱,構建了強大的跨平台運行環境。理解類別載入流程、運行時資料區劃分、GC 演算法演進、JIT 編譯優化,是 Java 進階工程師進行效能調優、疑難排查、架構選型的核心內功。