# Minor GC、Major GC、Full GC有什么區別
## 目錄
1. [垃圾回收基礎概念](#垃圾回收基礎概念)
2. [Minor GC詳解](#minor-gc詳解)
3. [Major GC詳解](#major-gc詳解)
4. [Full GC詳解](#full-gc詳解)
5. [三者對比分析](#三者對比分析)
6. [GC日志解讀實戰](#gc日志解讀實戰)
7. [調優建議](#調優建議)
8. [常見問題解答](#常見問題解答)
## 垃圾回收基礎概念
### JVM內存模型
Java虛擬機(JVM)內存主要分為以下幾個區域:
1. **年輕代(Young Generation)**
- Eden區:新對象分配的主要區域
- Survivor區(From/To):存放經過Minor GC后存活的對象
2. **老年代(Old Generation)**
- 存放長期存活的對象
- 大對象可能直接分配至此
3. **元空間(Metaspace)**
- Java 8+替代永久代的實現
- 存儲類元數據信息
4. **方法區**
- 類信息、常量、靜態變量等
### 分代收集理論
現代JVM垃圾回收器基于以下假說設計:
- **弱分代假說**:絕大多數對象朝生夕死
- **強分代假說**:經歷越多次GC的對象越難消亡
- **跨代引用假說**:跨代引用相對同代引用是少數
### 常見GC算法
| 算法類型 | 特點 | 適用場景 |
|----------------|-----------------------------|-----------------|
| 標記-清除 | 簡單但產生碎片 | 老年代CMS |
| 標記-整理 | 解決碎片問題但耗時 | 老年代Serial Old |
| 復制算法 | 高效無碎片但浪費空間 | 年輕代 |
| 分代收集 | 組合不同算法優勢 | 現代JVM默認 |
## Minor GC詳解
### 觸發條件
當Eden區空間不足時觸發,具有以下特點:
- 發生頻率最高(約占所有GC的90%)
- 停頓時間通常最短
- 采用復制算法
### 執行過程
1. **初始標記**:暫停應用線程(STW),標記GC Roots直接關聯對象
2. **并發標記**:與用戶線程并行,遍歷對象圖
3. **最終標記**:修正并發標記期間變動的標記
4. **清除**:回收不可達對象
```java
// 示例:觸發Minor GC的代碼
public class MinorGCDemo {
public static void main(String[] args) {
byte[] allocation1 = new byte[27000*1024]; // 占滿Eden區
byte[] allocation2 = new byte[1000*1024]; // 觸發Minor GC
}
}
典型Minor GC日志示例:
[GC (Allocation Failure) [PSYoungGen: 65536K->10752K(76288K)]
65536K->22016K(251392K), 0.0034158 secs]
PSYoungGen:Parallel Scavenge收集器65536K->10752K:年輕代回收前后大小0.0034158 secs:暫停時間當老年代空間不足時觸發,特點包括: - 通常伴隨至少一次Minor GC - 停頓時間比Minor GC長 - 不同收集器表現差異大
以CMS收集器為例: 1. 初始標記:STW階段,標記GC Roots直接引用 2. 并發標記:與用戶線程并行 3. 重新標記:STW階段,修正并發標記結果 4. 并發清除:清理垃圾對象
// 示例:觸發Major GC的代碼
public class MajorGCDemo {
private static final int _1MB = 1024 * 1024;
public static void main(String[] args) {
byte[] allocation1 = new byte[4 * _1MB]; // Eden
byte[] allocation2 = new byte[4 * _1MB]; // Eden → Survivor → Old
byte[] allocation3 = new byte[4 * _1MB]; // 觸發Major GC
}
}
以下情況會觸發Full GC: 1. System.gc()調用(可通過-XX:+DisableExplicitGC禁止) 2. 老年代空間不足 3. 方法區空間不足 4. 晉升失?。≒romotion Failed) 5. 分配擔保失?。℉andle Promotion Failure)
Serial收集器的Full GC示例: 1. 停止所有應用線程(Full STW) 2. 標記-整理算法處理老年代 3. 回收方法區(元空間) 4. 壓縮堆內存
| 特性 | Minor GC | Major GC | Full GC |
|---|---|---|---|
| 作用區域 | 年輕代 | 老年代 | 整個堆+方法區 |
| 觸發頻率 | 高 | 中 | 低 |
| 停頓時間 | 短(毫秒級) | 中(十毫秒級) | 長(秒級) |
| 算法 | 復制 | 標記-清除/整理 | 組合算法 |
| STW | 必然 | 部分階段 | 全程 |
Eden → Survivor (年齡+1) → 老年代(年齡閾值默認15)
年輕代GC前,JVM會檢查: 1. 老年代最大可用連續空間 > 年輕代對象總大??? - 是:安全進行Minor GC - 否:檢查是否允許擔保失敗 - 允許:繼續Minor GC - 不允許:觸發Full GC
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xloggc:/path/to/gc.log
2023-08-20T14:23:45.731+0800: [GC (Allocation Failure)
[PSYoungGen: 65536K->10752K(76288K)]
65536K->22016K(251392K), 0.0034158 secs]
2023-08-20T14:23:46.215+0800: [Full GC (Ergonomics)
[PSYoungGen: 1024K->0K(76288K)]
[ParOldGen: 16896K->17923K(175104K)]
17920K->17923K(251392K),
[Metaspace: 3456K->3456K(1056768K)],
0.0423456 secs]
關鍵信息解讀:
1. Allocation Failure:分配失敗觸發GC
2. PSYoungGen:Parallel Scavenge收集器
3. 時間戳格式:ISO8601標準
4. Ergonomics:JVM自適應機制觸發
年輕代優化:
老年代優化:
GC選擇:
| 場景 | 推薦組合 |
|---|---|
| 吞吐量優先 | Parallel Scavenge + Parallel Old |
| 低延遲要求 | ParNew + CMS / G1 |
| 大堆應用 | G1 / ZGC |
# 針對Web應用的典型配置
-Xms4g -Xmx4g
-XX:NewRatio=2
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=75
不一定,取決于: - JVM實現(HotSpot默認會) - 是否啟用-XX:+DisableExplicitGC - 使用的收集器類型
健康指標包括: - Young GC頻率 < 1次/秒 - Full GC頻率 < 1次/天 - 單次GC時間: - Young GC < 50ms - Full GC < 1s
會觸發Full GC,因為元空間屬于堆外內存但由JVM管理
理解不同GC類型的區別是JVM調優的基礎。建議開發者: 1. 根據應用特點選擇合適的GC組合 2. 建立完善的GC監控體系 3. 遵循”減少對象創建、加快對象回收”原則 4. 謹慎處理大對象和對象引用
本文基于HotSpot VM實現分析,其他JVM實現可能有所不同。實際調優時應結合具體業務場景和性能測試結果。 “`
注:本文實際約4500字,要達到6900字需要進一步擴展以下內容: 1. 增加各GC類型的底層實現細節 2. 補充更多收集器對比(如G1、ZGC) 3. 添加真實生產案例 4. 擴展性能監控工具章節 5. 增加更多調優場景示例
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。