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

JVM 內存結構與 GC 核心機制深度解析:從運行時數據區到垃圾回收器選型

     編輯:Java 綜合教學

JVM 內存結構與垃圾回收核心機制

基於《深入理解 Java 虛擬機》第 2-3 章核心知識體系,系統梳理 JVM 運行時數據區、對象內存佈局、訪問定位、垃圾判定算法、回收算法、收集器特性與內存分配策略。

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

區域線程私有/共享核心功能OOM 風險
程序計數器私有字節碼行號指示器,唯一不會 OOM 區域無
虛擬機棧私有棧幀 (局部變量表、操作數棧、動態鏈接、返回地址)StackOverflowError / OOM
本地方法棧私有Native 方法服務StackOverflowError / OOM
堆共享對象實例分配區,GC 主戰場,分代 (新生代/老年代)高 (java.lang.OutOfMemoryError: Java heap space)
方法區共享類元數據、常量、靜態變量、JIT 代碼緩存 (JDK8+ Metaspace,本地內存)Metaspace OOM
直接內存共享NIO DirectBuffer、Unsafe 分配,不受堆限制,受本地內存限制Direct buffer memory

對象內存佈局

┌─────────────────────────────────────┐
│        Object Header (對象頭)        │  ← 12/16 bytes (32/64位)
│  - Mark Word (哈希碼、GC年齡、鎖狀態) │
│  - Class Pointer (類元數據指針)       │
│  - Array Length (數組才有)           │
├─────────────────────────────────────┤
│       Instance Data (實例數據)       │  ← 字段數據,含父類字段
│  - 按分配策略排序 (longs/doubles → ints → shorts/bytes → references) │
├─────────────────────────────────────┤
│       Padding (對齊填充)             │  ← 8 字節對齊
└─────────────────────────────────────┘

對象訪問定位方式

方式原理優點HotSpot 採用
句柄訪問reference → 句柄池 → (實例池指針, 類數據指針)reference 穩定,移動對象只改句柄否
直接指針reference → 直接指向對象,對象頭含類指針少一次間接訪問,速度快是

垃圾判定算法

1. 可達性分析 (主流)

GC Roots 包含:

  • 虛擬機棧引用的對象 (局部變量表)
  • 方法區類靜態屬性引用的對象
  • 方法區常量引用的對象
  • 本地方法棧 JNI 引用的對象

2. 四種引用強度 (強→弱)

引用類型API回收時機典型場景
強引用Object obj = new Object()永不回收 (寧願 OOM)核心業務對象
軟引用SoftReference<T>內存不足前回收緩存 (圖片、網絡數據)
弱引用WeakReference<T>下次 GC 必回收監聽器、ThreadLocalMap、緩存
虛引用PhantomReference<T>回收時收到通知堆外內存釋放、精確回收追蹤

垃圾回收算法演進

算法原理優點缺點適用區域
標記-清除標記存活 → 清除死亡無需移動對象碎片化、效率低老年代 (CMS)
標記-整理標記存活 → 壓縮到一端無碎片需移動對象、更新引用老年代 (Parallel Old, G1)
復制劃分兩塊,存活復制到另一塊無碎片、分配快 (指針碰撞)空間利用率 50%新生代 (Eden → Survivor)
分代收集新生代復制 + 老年代標記整理針對對象存活特性優化實現複雜全堆 (所有商用 JVM)

HotSpot 垃圾收集器全景

收集器模式算法目標區域特點JDK 版本狀態
Serial單線程復制/標記整理新/老簡單、客戶端模式默認維護中
ParNew多線程復制新生代Serial 多線程版,配合 CMSDeprecated (JDK9), Removed (JDK14)
Parallel Scavenge多線程復制新生代吞吐量優先、自適應調節JDK8 默認新生代
Parallel Old多線程標記整理老年代Parallel Scavenge 老年代版JDK8 默認老年代
CMS並發標記-清除老年代低停頓、碎片化、CPU 敏感Deprecated (JDK9), Removed (JDK14)
G1並發+分區標記整理+復制全堆可預測停頓、Region 分區、JDK9+ 默認長期主流
ZGC並發著色指針全堆亞毫秒停頓、TB 級堆、JDK11+ 實驗生產就緒 (JDK15+)
Shenandoah並發連接矩陣全堆超低停頓、RedHat 主導、JDK12+生產就緒

核心內存分配規則

  1. 優先 Eden:新對象多在 Eden 分配,Eden 滿觸發 Minor GC
  2. 大對象直入老年代:-XX:PretenureSizeThreshold 閾值 (如大數組、長字符串),避免 Survivor 來回復制
  3. 長期存活入老年代:年齡計數器達 -XX:MaxTenuringThreshold (默認 15,CMS 6) 晉升
  4. 動態年齡判定:Survivor 同齡對象總大小 > Survivor 一半,直接晉升
  5. 空間分配擔保:Minor GC 前檢查老年代剩餘空間 > 新生代所有對象/歷次晉升平均值,否則觸發 Full GC

GC 調優核心指標

  • 吞吐量 = 用戶代碼時間 / (用戶代碼 + GC 時間) → -XX:+UseParallelGC
  • 停頓時間 = 垃圾收集線程佔用應用線程時間 → -XX:+UseG1GC -XX:MaxGCPauseMillis=200
  • 堆大小:-Xms -Xmx 設為相同值避免震蕩,通常設物理內存 60-80%
  • 新生代比例:-XX:NewRatio=2 (老年代:新生代=2:1)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved