您好,登录后才能下订单哦!
# 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. 晋升失败(Promotion Failed) 5. 分配担保失败(Handle 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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。