Java 體系四大支柱
- Java 程式語言:語法、特性、語義
- Class 檔案格式:位元碼、常量池、類元資料結構
- Java API (類庫):基礎類、集合、I/O、網路、並發等標準庫
- Java 虛擬機 (JVM):載入/驗證/執行 Class 檔案、記憶體管理、即時編譯
四者獨立但緊密關聯:語言編譯為 Class,API 提供運行時支撐,JVM 載入執行。
JVM 核心職責
- 載入 Class 檔案:透過類載入器子系統
- 執行位元碼:透過執行引擎 (解釋器 + JIT 編譯器)
- 記憶體管理:堆/棧/方法區分配、垃圾回收
- 本地方法介接:JNI 連接 C/C++ 等本地代碼
執行引擎演進四階段
| 階段 | 技術 | 特點 |
| 1 | 純解釋執行 | 逐條解釋位元碼,啟動快、執行慢 |
| 2 | 即時編譯器 (JIT) | 熱點代碼編譯為機器碼緩存,後續重用,平衡啟動/峰值效能 |
| 3 | 自適應優化器 | 動態識別熱點方法、內聯、逃逸分析、鎖消除等進階優化 |
| 4 | 硬體實現 (Jazelle 等) | 位元碼直接在晶片執行,嵌入式/特定場景 |
兩類方法
- Java 方法:由 Java 語言實現,編譯為位元碼,JVM 管理
- 本地方法:由 C/C++/組合語言實現,編譯為機器碼動態庫 (.so/.dll),透過 JNI 呼叫
本地方法是 Java 程式與作業系統/硬體資源的橋梁 (如檔案 I/O、網路、圖形介面)。
類載入器體系
| 載入器 | 職責 | 父子關係 |
| 啟動類載入器 | 載入核心類庫 (<JAVA_HOME>/lib/rt.jar 等) | 頂層,C++ 實現,無父載入器 |
| 擴展類載入器 | 載入擴展庫 (<JAVA_HOME>/lib/ext) | 父為啟動載入器 |
| 應用程式類載入器 | 載入類路徑 (-cp) 下的類 | 父為擴展載入器,預設系統載入器 |
| 使用者自定義載入器 | 特殊來源 (網路、加密、資料庫等) | 父通常為應用程式載入器 |
雙親委派模型:載入請求先委派給父載入器,層層向上;父無法載入時子才嘗試。確保核心類庫安全、避免重複載入。
Class 檔案格式
- 平台無關的二進制格式
- 包含:魔數、版本、常量池、存取標誌、類/父類/介面索引、欄位表、方法表、屬性表
- 常量池是「資源倉庫」:字面量、符號引用、類/方法/欄位符號引用
Java API 角色
提供存取宿主資源的標準介面:檔案系統、網路、執行緒、圖形介面、資料庫連線等。JVM 透過本地方法實現 API 底層邏輯。
運行時資料區 (JMM 核心)
| 區域 | 線程私有/共享 | 核心內容 | OOM 風險 |
| 程式計數器 (PC Register) | 私有 | 當前執行位元碼指令地址 | 無 |
| Java 虛擬機棧 | 私有 | 棧幀 (局部變數表、操作數棧、動態連結、方法返回地址) | StackOverflowError (深遞歸) |
| 本地方法棧 | 私有 | 本地方法執行上下文 | StackOverflowError |
| Java 堆 | 共享 | 物件實例、陣列 (GC 主戰場) | OutOfMemoryError: Java heap space |
| 方法區 / Metaspace (JDK 8+) | 共享 | 類元資料、常量、靜態變數、JIT 編譯代碼緩存 | OutOfMemoryError: Metaspace |
| 直接記憶體 | 共享 (堆外) | NIO DirectBuffer、JNI 分配 | OutOfMemoryError: Direct buffer memory |
學習心得與建議
「話說不想做一個只會寫 if(){}else{} 的程式員就得努力學習...姑且好好理解下 Java 底層吧。」
- JVM 知識是從「API 呼叫者」進階為「系統設計者」的分水嶺
- 建議學習路徑:運行時資料區 → 垃圾回收 → 類載入 → 執行引擎 → 效能調優
- 工具掌握:jstack/jmap/jstat/jconsole/VisualVM/Arthas/Async-profiler
- 實戰場景:OOM 排查、GC 停頓分析、類載入衝突、鎖競爭、JIT 編譯行為
- 上一篇文章: Java 集合框架核心體系速覽:List、Set、Map 三大介面與主流實作特徵
- 下一篇文章: 九度 OJ 1473 題解:無符號整數轉二進制字串 (去除前導零)
Copyright ©
程式碼之家 All Rights Reserved