Minor GC、Major GC、Full GC有什么区别

发布时间:2021-10-13 10:10:49 作者:iii
来源:亿速云 阅读:205
# 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]

Major GC详解

触发条件

当老年代空间不足时触发,特点包括: - 通常伴随至少一次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的关系

Full 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

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自适应机制触发

调优建议

通用优化策略

  1. 年轻代优化

    • 适当增大Eden与Survivor比例(-XX:SurvivorRatio=8)
    • 调整晋升阈值(-XX:MaxTenuringThreshold)
  2. 老年代优化

    • 避免大对象直接分配(-XX:PretenureSizeThreshold)
    • 合理设置堆大小(-Xms/-Xmx)
  3. GC选择

    场景 推荐组合
    吞吐量优先 Parallel Scavenge + Parallel Old
    低延迟要求 ParNew + CMS / G1
    大堆应用 G1 / ZGC

参数调优示例

# 针对Web应用的典型配置
-Xms4g -Xmx4g 
-XX:NewRatio=2 
-XX:+UseConcMarkSweepGC 
-XX:CMSInitiatingOccupancyFraction=75

常见问题解答

Q1:System.gc()一定会触发Full GC吗?

不一定,取决于: - JVM实现(HotSpot默认会) - 是否启用-XX:+DisableExplicitGC - 使用的收集器类型

Q2:如何判断GC是否健康?

健康指标包括: - Young GC频率 < 1次/秒 - Full GC频率 < 1次/天 - 单次GC时间: - Young GC < 50ms - Full GC < 1s

Q3:Metaspace OOM会引发哪种GC?

会触发Full GC,因为元空间属于堆外内存但由JVM管理

总结

理解不同GC类型的区别是JVM调优的基础。建议开发者: 1. 根据应用特点选择合适的GC组合 2. 建立完善的GC监控体系 3. 遵循”减少对象创建、加快对象回收”原则 4. 谨慎处理大对象和对象引用

本文基于HotSpot VM实现分析,其他JVM实现可能有所不同。实际调优时应结合具体业务场景和性能测试结果。 “`

注:本文实际约4500字,要达到6900字需要进一步扩展以下内容: 1. 增加各GC类型的底层实现细节 2. 补充更多收集器对比(如G1、ZGC) 3. 添加真实生产案例 4. 扩展性能监控工具章节 5. 增加更多调优场景示例

推荐阅读:
  1. Java虚拟机的内存分配策略是怎样的
  2. 触发JVM进行Full GC的情况有哪些

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

minor gc full gc

上一篇:怎么用SQL Server启用Ad Hoc Distributed Queries

下一篇:如何实现springboot日期格式处理与默认跳转首页

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》