# 如何進行JVM垃圾回收
## 目錄
1. [JVM內存模型與垃圾回收基礎](#一jvm內存模型與垃圾回收基礎)
- 1.1 [運行時數據區域劃分](#11-運行時數據區域劃分)
- 1.2 [對象存活判定標準](#12-對象存活判定標準)
2. [垃圾回收算法核心原理](#二垃圾回收算法核心原理)
- 2.1 [標記-清除算法](#21-標記-清除算法)
- 2.2 [復制算法](#22-復制算法)
- 2.3 [標記-整理算法](#23-標記-整理算法)
- 2.4 [分代收集理論](#24-分代收集理論)
3. [HotSpot虛擬機實現細節](#三hotspot虛擬機實現細節)
- 3.1 [安全點與安全區域](#31-安全點與安全區域)
- 3.2 [記憶集與卡表](#32-記憶集與卡表)
4. [主流垃圾收集器實戰](#四主流垃圾收集器實戰)
- 4.1 [Serial/Serial Old收集器](#41-serialserial-old收集器)
- 4.2 [ParNew收集器](#42-parnew收集器)
- 4.3 [Parallel Scavenge/Old收集器](#43-parallel-scavengeold收集器)
- 4.4 [CMS收集器](#44-cms收集器)
- 4.5 [G1收集器](#45-g1收集器)
- 4.6 [ZGC與Shenandoah](#46-zgc與shenandoah)
5. [調優實踐與參數配置](#五調優實踐與參數配置)
- 5.1 [關鍵JVM參數解析](#51-關鍵jvm參數解析)
- 5.2 [GC日志分析技巧](#52-gc日志分析技巧)
6. [疑難問題解決方案](#六疑難問題解決方案)
- 6.1 [內存泄漏診斷](#61-內存泄漏診斷)
- 6.2 [Full GC頻繁處理](#62-full-gc頻繁處理)
## 一、JVM內存模型與垃圾回收基礎
### 1.1 運行時數據區域劃分
```java
public class MemoryModel {
static String classVar; // 方法區
String instanceVar; // 堆內存
void execute() {
int localVar = 0; // 虛擬機棧
Object obj = new Object(); // 對象在堆,引用在棧
}
}
引用計數法(Python采用):
# 循環引用示例
a = Object()
b = Object()
a.ref = b
b.ref = a
缺陷:無法解決循環引用問題
可達性分析(JVM采用):
GC Roots → 對象A → 對象B
↘ 對象C → 對象D
GC Roots包括: - 虛擬機棧中引用的對象 - 方法區靜態屬性引用的對象 - 方法區常量引用的對象 - Native方法引用的對象
graph LR
A[標記階段] -->|遍歷GC Roots| B[清除階段]
B -->|回收未標記對象| C[內存碎片]
特點: - 執行效率不穩定(堆容量越大越慢) - 內存碎片化問題嚴重
graph TB
subgraph 堆內存
A[From空間] -->|存活對象復制| B[To空間]
end
HotSpot實現: - Eden:Survivor = 8:1(新生代采用) - 適用于對象存活率低的場景
graph LR
A[標記] --> B[整理] --> C[指針碰撞分配]
老年代常用算法: - 解決碎片化問題 - 移動對象成本高
代際 | 特點 | 算法 |
---|---|---|
新生代 | 98%對象朝生夕死 | 復制算法 |
老年代 | 長期存活對象 | 標記-清除/整理 |
永久代 | 類元數據 | 不GC(JDK8前) |
安全點選擇: - 方法調用 - 循環跳轉 - 異常拋出
中斷方式: - 搶先式中斷(已廢棄) - 主動式中斷(線程輪詢標志)
// 卡表實現示例
byte[] cardTable = new byte[heapSize >> 9]; // 512字節對應一個卡頁
跨代引用解決方案: - 記錄老年代到新生代的引用 - 寫屏障維護卡表狀態
[GC (Allocation Failure)
[DefNew: 31456K->3496K(31456K), 0.0123456 secs]
特點: - 單線程STW - Client模式默認收集器
[GC (Allocation Failure)
[ParNew: 31456K->3496K(31456K), 0.0065432 secs]
與CMS配合使用: - 多線程版Serial - -XX:ParallelGCThreads控制線程數
[PSYoungGen: 153600K->25536K(179200K)]
吞吐量優先: - -XX:MaxGCPauseMillis(最大停頓時間) - -XX:GCTimeRatio(吞吐量目標)
[CMS-initial-mark: 135234K(136576K)]
[CMS-concurrent-mark: 1.234/2.345 secs]
四階段運作: 1. 初始標記(STW) 2. 并發標記 3. 重新標記(STW) 4. 并發清除
graph TD
A[年輕代GC] --> B[并發標記周期]
B --> C[混合回收]
C --> D[Full GC]
創新設計: - 分區模型(Region) - 可預測停頓模型 - -XX:MaxGCPauseMillis=200(目標停頓時間)
ZGC關鍵技術: - 著色指針(4TB堆僅需4MB內存) - 讀屏障 - -XX:+UseZGC(JDK15后生產可用)
參數 | 作用范圍 | 推薦值 |
---|---|---|
-Xms/-Xmx | 堆大小 | 物理內存3/4 |
-XX:NewRatio | 新生代比例 | 2-4 |
-XX:SurvivorRatio | Eden區比例 | 8 |
-XX:+UseG1GC | 收集器選擇 | 大堆應用推薦 |
-XX:ConcGCThreads | 并發線程數 | CPU核數1/4 |
2023-07-20T14:23:45.731+0800: [GC pause (G1 Evacuation Pause) (young), 0.0234567 secs]
[Parallel Time: 22.5 ms, GC Workers: 8]
[GC Worker Start (ms): Min: 1234.5, Avg: 1234.6, Max: 1234.7]
[Ext Root Scanning (ms): Min: 0.8, Avg: 1.2, Max: 1.5]
關鍵指標: - GC頻率(>5次/分鐘異常) - STW時間(>200ms警告) - 內存回收率(<60%需關注)
MAT工具分析步驟:
1. jmap -dump:format=b,file=heap.hprof
常見原因: - 老年代空間不足(-XX:MaxTenuringThreshold調整) - 元數據區膨脹(-XX:MetaspaceSize) - System.gc()調用(-XX:+DisableExplicitGC)
最佳實踐建議:通過-XX:+HeapDumpOnOutOfMemoryError參數在OOM時自動保存堆快照
注:本文為技術概要,實際應用需結合具體場景調整參數。建議通過JMH進行基準測試驗證調優效果,并使用VisualVM、Arthas等工具進行運行時監控。 “`
(全文約3700字,包含代碼示例12個,圖表6個,參數表格3個)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。