当前位置: 首页 > news >正文

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

一、Minor GC 触发条件

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

// 循环创建对象填满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后存活对象需进入老年代,但老年代剩余空间不足。
• 大对象分配失败:老年代无法容纳新的大对象。

示例代码:

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是全局性回收,通常意味着内存配置不合理或存在内存泄漏,需结合日志和监控深入分析。
• 优化方向:降低对象分配速率、合理划分堆内存、选择合适的垃圾收集器。

相关文章:

  • DeepSeek驱动的智能客服革命:语音交互与大模型的融合实践
  • keep the pipe Just full But no fuller - BBR 与尘封 40 年的求索
  • 复刻低成本机械臂 SO-ARM100 单关节控制(附代码)
  • 基于STM32、HAL库的CP2102-GMR USB转UART收发器 驱动程序设计
  • 分享 2 款基于 .NET 开源的实时应用监控系统
  • wails3学习-runtime:Window无边框设置
  • 【Spring Boot 多模块项目】@MapperScan失效、MapperScannerConfigurer 报错终极解决方案
  • window 显示驱动开发-处理内存段(二)
  • Linux系统下使用Kafka和Zookeeper
  • 中介者模式(Mediator Pattern)详解
  • TI AM243X开发流程
  • 【Python 字符串】
  • 大模型的应用中A2A(Agent2Agent)架构的部署过程,A2A架构实现不同机器人之间的高效通信与协作
  • Redis 重回开源怀抱:开源精神的回归与未来展望
  • 仓储车间安全革命:AI叉车防撞装置系统如何化解操作风险
  • 中科院开源:多智能体 + 知识图谱,自动生成高质量医学数据
  • SAP 交货单行项目含税金额计算报cx_sy_zerodivide处理
  • 【人工智能】低代码与AI技术未来趋势分析
  • Redis 8.0正式发布,再次开源为哪般?
  • SQL:MySQL函数:字符串函数
  • 菲护卫艇企图侵闯中国黄岩岛领海,南部战区:依法依规跟踪监视、警告驱离
  • 现场|万里云端,遇见上博
  • 央行:将支持资本市场两项货币政策工具的额度合并使用
  • 短剧剧组在贵州拍戏突遇极端天气,演员背部、手臂被冰雹砸伤
  • 秦洪看盘|涌现新逻辑,A股放量回升
  • 有乘客被高铁车门夹住?铁路回应:系突感不适下车,未受伤,列车正点发车