Minor GC与Full GC分别在什么时候发生?

一、Minor GC 触发条件

1.Eden区空间不足

• 核心机制:新对象优先分配在Eden区,当Eden区无法满足新对象分配时触发Minor GC。

示例:

java 复制代码
// 循环创建对象填满Eden区
for (int i = 0; i < 1000000; i++) {
    byte[] data = new byte[1 * 1024]; // 持续分配1KB对象
}

细节:

• 存活对象会复制到Survivor区(From/To区交替使用)。

• 若Survivor区空间不足,则通过"分配担保"(Handle Promotion)直接进入老年代。

2.大对象直接进入老年代

• 规则:超过-XX:PretenureSizeThreshold参数值的大对象(如缓存、大数组)直接在老年代分配,避免Eden区频繁GC。

配置示例:

-XX:PretenureSizeThreshold=2M # 超过2MB的对象直接进入老年代

3.动态年龄判定

• 规则:Survivor区中一批对象的年龄总和超过Survivor区空间的50%,则年龄≥该阈值的对象提前晋升到老年代(即使未达到-XX:MaxTenuringThreshold)。

二、Full GC 触发条件

1.老年代空间不足

场景:

• 晋升失败:Minor GC后存活对象需进入老年代,但老年代剩余空间不足。

• 大对象分配失败:老年代无法容纳新的大对象。

示例代码:

java 复制代码
List<byte[]> oldGenList = new ArrayList<>();
while (true) {
    oldGenList.add(new byte[10 * 1024 * 1024]); // 持续在老年代分配10MB对象
}

2.元空间(Metaspace)不足

触发条件:

• 加载的类信息、常量池等元数据超过-XX:MetaspaceSize阈值。

• 频繁动态生成类(如反射、CGLIB代理)。

配置建议:

-XX:MetaspaceSize=128M

-XX:MaxMetaspaceSize=256M

3.显式调用System.gc()

行为:建议JVM执行Full GC,但可通过参数禁止响应:

-XX:+DisableExplicitGC # 忽略System.gc()

4. 垃圾收集器策略触发

CMS收集器:

• 并发模式失败(Concurrent Mode Failure)时,退化为Serial Old收集器执行Full GC。

• 老年代碎片化严重,无法找到连续空间分配对象。

G1收集器:

• 混合回收(Mixed GC)无法跟上分配速度时触发Full GC。

三、GC触发逻辑对比

四、优化建议

减少Full GC频率:

• 增大老年代比例(-XX:NewRatio调整新生代/老年代比例)。

• 避免过大的内存分配(分页加载数据、压缩对象)。
监控工具:

• 通过GC日志分析(-Xloggc:/path/to/gc.log)定位频繁GC原因。

• 使用VisualVM、Grafana + Prometheus监控堆内存分布。
收集器选择:

• 高吞吐场景:Parallel Scavenge + Parallel Old。

• 低延迟场景:CMS或G1(JDK9+默认)。

五、实战案例

场景:电商大促期间频繁Full GC

现象:每秒订单量激增,老年代2秒内填满,频繁Full GC导致服务卡顿。

根因分析:

• 订单处理中临时对象(如JSON解析结果)未及时释放,晋升到老年代。

• 本地缓存(Guava Cache)未设置软引用或大小限制,长期占用老年代。

优化方案:

增加本地缓存失效时间:cache.expireAfterWrite(5, TimeUnit.MINUTES)。

调整新生代大小:-XX:NewRatio=1(新生代与老年代1:1)。

启用G1收集器:-XX:+UseG1GC -XX:MaxGCPauseMillis=200。

总结

• Minor GC是高频但低影响的常规回收,核心关注Eden区分配速率和Survivor区对象年龄。

• Full GC是全局性回收,通常意味着内存配置不合理或存在内存泄漏,需结合日志和监控深入分析。

• 优化方向:降低对象分配速率、合理划分堆内存、选择合适的垃圾收集器。

相关推荐
alden_ygq10 小时前
当java进程内存使用超过jvm设置大小会发生什么?
java·开发语言·jvm
多敲代码防脱发13 小时前
导出导入Excel文件(详解-基于EasyExcel)
java·开发语言·jvm·数据库·mysql·excel
北漂老男孩16 小时前
JVM对象头中的锁信息机制详解
jvm
黄雪超17 小时前
JVM——方法内联之去虚化
java·开发语言·jvm
xinxiyinhe17 小时前
内存泄漏与OOM崩溃根治方案:JVM与原生内存池差异化排查手册
java·开发语言·jvm
PgSheep20 小时前
深入理解 JVM:StackOverFlow、OOM 与 GC overhead limit exceeded 的本质剖析及 Stack 与 Heap 的差异
jvm·面试
意倾城1 天前
JVM 如何优化 31 * x 为 (x << 5) - x?
java·jvm
LUCIAZZZ1 天前
JVM之内存管理(一)
java·jvm·spring·操作系统·springboot
小王努力学编程2 天前
高并发内存池(三):TLS无锁访问以及Central Cache结构设计
jvm·数据结构·c++·学习