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

JVM 內存分配與 GC 全景圖:分代模型、參數調優、溢出排查與四大收集器選型

     編輯:Java 綜合教學

分代假設與內存結構

核心假設:絕大多數對象朝生夕死(適合新生代複製算法),少數對象存活久(適合老年代標記整理)。

JVM Heap
├── Young Generation (新生代)
│   ├── Eden Space (伊甸區)          ← 新對象優先分配
│   ├── Survivor 0 (From)            ← Minor GC 存活對象
│   └── Survivor 1 (To)              ← 輪換角色,保證一個始終為空
└── Old Generation (老年代)           ← 多次 Minor GC 存活晋升
    └── (Tenured Space)
Metaspace (元空間, 非堆)              ← 類元數據、常量池、方法表 (JDK 8+ 替代 PermGen)

對象分配與晋升流程

  1. 優先 Eden:新對象在 Eden 分配(TLAB 線程本地緩衝加速)。
  2. Minor GC 觸發:Eden 滿 → STW,存活對象複製到 Survivor (From)。
  3. Survivor 輪換:下次 Minor GC,From + Eden 存活對象複製到 To,清空 From/Edens,角色互換。
  4. 晋升老年代:對象年齡達到 -XX:MaxTenuringThreshold (默認 15) 或 Survivor 放不下 → 直接進老年代。
  5. 大對象直入老年代:-XX:PretenureSizeThreshold 超過閾值繞過新生代。
  6. Full GC 觸發:老年代滿、Metaspace 滿、System.gc()、動態策略調整。

關鍵 JVM 參數速查

參數含義生產建議
-Xms / -Xmx堆初始/最大值設為相同值,避免動態擴縮容開銷
-Xmn / -XX:NewSize / -XX:MaxNewSize新生代大小約佔堆 1/3~1/2,固定值
-XX:SurvivorRatioEden:Survivor 比例默認 8:1:1,大對象多可調大 Survivor
-XX:PermSize / -XX:MaxPermSize永久代 (JDK 7)JDK 8+ 改用 Metaspace
-XX:MetaspaceSize / -XX:MaxMetaspaceSize元空間大小根據類加載量設定,防止無限增長
-Xss線程棧大小256k~1M,過大限制線程數,過小棧溢出
-XX:+HeapDumpOnOutOfMemoryErrorOOM 時導出堆快照生產必開,配合 -XX:HeapDumpPath

四大 GC 收集器對比 (JDK 7/8 視角)

收集器模式適用場景啟用參數特點
Serial GC單線程 STWClient 模式、單核、小堆-XX:+UseSerialGC簡單、無線程切換開銷
Parallel GC (Throughput)多線程 STW多核、批處理、高吞吐優先-XX:+UseParallelGC新生代並行,老年代串行 (JDK 8+ 老年代也並行)
CMS (Concurrent Mark Sweep)並發標記+清除多核、低延遲、響應時間敏感-XX:+UseConcMarkSweepGC碎片化風險,需定期 Full GC 整理,JDK 9 標記棄用
G1 (Garbage First)分區並發+混合收集大堆 (4G+)、可預測停頓、JDK 9+ 默認-XX:+UseG1GCRegion 劃分、優先回收垃圾多區、可配置目標停頓

常見 OOM 場景與排查

  1. Java Heap Space:老年代/新生代滿。
    → jmap -histo:live pid 統計對象、jhat/MAT 分析堆快照、檢查大對象/集合泄漏。
  2. Metaspace / PermGen:類加載過多 (動態代理、JSP 編譯、熱部署)。
    → 增大 MaxMetaspaceSize、檢查類加載器泄漏、-XX:+CMSClassUnloadingEnabled (CMS)。
  3. Direct Buffer Memory:NIO 直接內存/Netty/堆外緩存。
    → -XX:MaxDirectMemorySize 限制、排查 ByteBuffer.allocateDirect 未釋放。
  4. Unable to create native thread:線程過多/棧太大。
    → 減小 -Xss、優化線程池、檢查系統 ulimit -u/pid_max。

GC 日志分析模板

-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC -Xloggc:/var/log/gc-%t.log

關注指標:Young GC 頻率/耗時、Old GC 間隔/耗時、堆佔用率趨勢、晋升速率。健康系統:Young GC < 50ms、Old GC < 200ms、老年代佔用 < 70%、晋升率穩定。

調優口訣

「堆大小固定、新生代足夠、Survivor 能裝下存活集、避免大對象、選對收集器、日志必存、OOM 快照、壓測驗證」

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved