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是全局性回收,通常意味着内存配置不合理或存在内存泄漏,需结合日志和监控深入分析。

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

相关推荐
Tingjct9 小时前
线程详细讲解---聚焦linux
linux·服务器·jvm
myy-learn9 小时前
32 SQLITE数据库
jvm·数据库·sqlite
wuminyu12 小时前
JVM锁膨胀与Futex源码解析
java·linux·c语言·jvm·c++
郝学胜-神的一滴12 小时前
C++11 工程级应用 08:Lambda表达式与Tuple元组
开发语言·jvm·c++·python·程序人生·开源
袋鼠云数栈1 天前
整库迁移与分库分表同步:批量数据搬迁的配置简化思路
jvm·数据库·oracle
Mr. zhihao1 天前
JVM 偏向锁 4 秒延迟:从源码动机到 JEP-374 废弃全链路
jvm·并发·偏向锁
孙克旭_1 天前
JVM 入门详解:JVM、JRE、JDK 区别,JVM 基础结构梳理
java·开发语言·jvm
随遇而安zx1 天前
【地基篇】---JVM 内存结构知识点(Java 8 运行时数据区深度解析)
java·开发语言·jvm
恒拓高科WorkPlus1 天前
企业如何搭建安全内部通讯平台|企业内部通讯平台怎么选才更安全?
jvm·数据库·安全
随遇而安zx2 天前
【地基篇】---JVM 类加载 源码解析(基于 Java 8)
java·jvm·python