Java 虛擬機在執行程式時將管理的內存劃分為若干區域(JDK 1.8+ 元空間取代永久代):
| 區域 | 線程共享性 | 核心功能 |
|---|---|---|
| 程式計數器 | 私有 | 當前執行字節碼指令地址 |
| Java 虛擬機棧 | 私有 | 棧幀:局部變量表、操作數棧、動態連接、方法出口 |
| 本地方法棧 | 私有 | 服務 Native 方法 |
| Java 堆 | 共享 | 對象實例分配主戰場,GC 主戰場,分代:新生代/老年代 |
| 方法區 | 共享 | 類信息、常量、靜態變量、JIT 編譯代碼(1.8+ 元空間) |
| 運行時常量池 | 共享 | 方法區一部分,存編譯期常量與符號引用,String.intern() 操作此處 |
主流 JVM 採用可達性分析(非引用計數,避免循環引用問題):
| 引用類型 | 強度 | 回收時機 | 典型應用 |
|---|---|---|---|
| 強引用 | 最強 | 永不回收 | Object obj = new Object() |
| 軟引用 | 次強 | 記憶體不足前回收 | 緩存(SoftReference) |
| 弱引用 | 較弱 | 下次 GC 即回收 | 緩存、監聽器(WeakReference) |
| 虛引用 | 最弱 | 不影響生命週期,回收前收到通知 | 直接內存管理(PhantomReference) |
兩階段:標記存活 → 清除未標記。缺點:效率低、產生大量內存碎片。
內存劃分為大小相等兩塊,每次用一塊,存活對象複製到另一塊,再清理已用半區。優點:無碎片、分配簡單(指針碰撞)。缺點:內存利用率仅 50%。
→ 現代新生代優化:Eden : Survivor = 8:1:1,僅浪費 10% Survivor 空間。
標記後將存活對象向一端移動,清理邊界外內存。適用於老年代(存活率高、不適合複製)。
根據對象生命週期劃分區域,針對性選算法:
finalize() 可在 GC 首次標記後、第二次標記前執行一次「自救」(重新建立引用)。但:
Deprecated(JDK 9+),建議用 Cleaner / PhantomReference 替代。理解 JVM 內存劃分、可達性分析、引用類型與分代算法,是排查 OOM、優化 GC、設計緩存體系的理論基石。