首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 內存管理核心:堆棧結構、可達性分析 GC 與引用計數缺陷

     編輯:Java 綜合教學

Java 內存管理核心

理解 JVM 內存結構與垃圾回收原理,是定位 OOM、優化 GC 停頓、排查內存洩漏的基石。本文覆蓋運行時數據區、對象創建與訪問、GC 根枚舉、可達性分析算法、引用計數缺陷及現代收集器演進。

一、JVM 運行時數據區(JDK 1.8+)

JVM 內存結構
垃圾回收原理
區域線程共享性核心內容異常
堆共享對象實例、數組(GC 主戰場)OutOfMemoryError: Java heap space
虛擬機棧私有棧幀(局部變量表、操作數棧、動態鏈接、返回地址)StackOverflowError / OOM
本地方法棧私有Native 方法調用同上
方法區共享類元數據、常量、靜態變量、JIT 編譯代碼(元空間)OOM: Metaspace
程序計數器私有當前執行字節碼行號無

二、對象創建與訪問

  1. 創建:new 指令 → 類加載檢查 → 堆劃分內存(指針碰撸/空閒列表) → 初始化零值 → 設置對象頭(哈希碼、GC 信息、鎖狀態、類元數據指針) → 執行 <init> 構造器。
  2. 訪問:棧帧 reference → 堆對象。主流兩種方式:
    • 句柄池:reference → 句柄池 → 實例池/方法區(移動對象只改句柄)。
    • 直接指針:reference 直接指向對象(HotSpot 默認,節省一次間接訪問)。

三、垃圾回收核心判定:可達性分析

1. 引用計數法缺陷

早期嘗試:對象頭維護計數器,引用+1,釋放-1,歸零回收。致命缺陷:無法解決 循環引用(A→B,B→A,無外部引用時計數不為零)。

2. 可達性分析(GC Roots Tracing)

以 GC Roots 為起點,向下搜索引用鏈,可達對象存活,不可達對象判定為垃圾。

GC Roots 包含:

  • 虛擬機棧中引用的對象(局部變量表)。
  • 方法區中類靜態屬性引用的對象。
  • 方法區中常量引用的對象。
  • 本地方法棧中 JNI 引用的對象。
  • 活躍線程、同步鎖持有對象等。

四、引用類型與 GC 關係

引用類型強度GC 行為典型場景
強引用最強永不回收Object obj = new Object()
軟引用次強內存不足前回收緩存(SoftReference + HashMap)
弱引用較弱下次 GC 回收WeakHashMap、ThreadLocalMap
虛引用最弱跟蹤對象被回收時機PhantomReference + ReferenceQueue(直接內存釋放)

五、經典 GC 算法與分代收集

算法原理優點缺點應用代
標記-清除標記存活 → 清除死對象實現簡單碎片化、效率低老年代(CMS 初期)
標記-整理標記 → 移動存活對象一端 → 清理邊界外無碎片移動開銷大老年代(Parallel Old、G1 混合)
複製劃分兩塊,每次用一塊,存活複製到另一塊無碎片、分配快內存利用率 50%新生代(Eden + Survivor)

分代假說:多數對象朝生夕死(新生代用複製),少數熬過多次 GC 進老年代(老年代用標記-整理/混合)。

六、常見收集器概覽

  • Serial/Serial Old:單線程,Client 模式默認。
  • Parallel Scavenge/Parallel Old:多線程吞吐量優先,Server 模式默認(JDK 8)。
  • CMS:並發標記-清除,低停頓,碎片化問題,JDK 9 棄用。
  • G1:面向服務端,Region 分區,混合收集,可預測停頓,JDK 9+ 默認。
  • ZGC / Shenandoah:超大堆(TB 級),亞毫秒級停頓,JDK 11/12+ 實驗/產品化。

七、實戰排查技巧

  1. jmap -heap pid 查看堆佈局與 GC 策略。
  2. jstat -gcutil pid 1000 監控各代使用率與 GC 頻率。
  3. jmap -histo:live pid | head -20 定位大對象/洩漏候選。
  4. MAT / JVisualVM 分析 Heap Dump,追蹤 GC Roots 鏈路定位洩漏根因。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved