YGC过于频繁问题以及解决方案

 更新时间:2025年04月08日 10:36:41   作者:StayInLove  
这篇文章主要介绍了YGC过于频繁问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

频繁的 Young GC(YGC)通常反映JVM年轻代内存配置或对象分配机制存在问题,以下是针对性排查和优化方案:

一、快速定位瓶颈

实时监控指标

# 每2秒采集GC数据(替换PID)
jstat -gcutil <pid> 2000

# 关键指标解读:
- YGCT: Young GC总耗时
- YGC: Young GC次数
- EU/S0/S1: Eden/Survivor区使用率

正常情况:单次YGC耗时应<50ms,1分钟内YGC次数<5次

GC日志分析

启动参数追加:

-Xlog:gc*=debug:file=gc.log:time,uptime,level,tags:filecount=5,filesize=100m

使用 GCeasy 在线解析日志,重点关注:

  • 对象晋升速率(Promotion Rate)
  • 分配失败触发GC(Allocation Failure)

二、核心优化策略

A. 内存结构调整

参数典型场景计算公式
-XX:NewRatio=3老年代与年轻代比例 3:1NewSize=Heap/(NewRatio+1)
-XX:SurvivorRatio=8Eden与单个Survivor区比例 8:1:1Eden = Young/(SurvivorRatio+2)

动态计算工具:

使用 JVM Heap Calculator 可视化调整

B. 分配速率优化

1.对象池化

对频繁创建的短生命周期对象(如DTO)采用对象池:

// 使用Apache Commons Pool
GenericObjectPool<Request> pool = new GenericObjectPool<>(new BasePooledObjectFactory<>() {
    @Override public Request create() { return new Request(); }
});

2.堆外内存

对大型临时数据使用DirectByteBuffer:

ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 1024); // 1MB off-heap

C. 收集器专项优化

G1调优(推荐JDK8+)

-XX:+UseG1GC 
-XX:MaxGCPauseMillis=200        # 目标停顿时间
-XX:G1NewSizePercent=30        # 年轻代最小占比
-XX:G1MaxNewSizePercent=60     # 年轻代最大占比

ZGC低延迟方案(JDK15+)

-XX:+UseZGC -XX:ZAllocationSpikeTolerance=5.0

三、异常场景处理

案例1:过早提升(Premature Promotion)

现象:Survivor区频繁溢出,对象过早进入老年代

解决

-XX:TargetSurvivorRatio=60   # 控制Survivor空间利用率
-XX:+NeverTenure             # 禁止直接晋升(G1可用)

案例2:内存泄漏

堆转储分析

jmap -dump:live,format=b,file=heap.bin <pid>

用MAT工具检查Retained Heap最大的对象

弱引用监控

WeakReference<Object> ref = new WeakReference<>(largeObj);
if (ref.get() == null) System.out.println("对象已被回收");

四、终极应急方案

当无法立即修改代码时,内存急救措施

# 临时扩容年轻代(不重启JVM)
jcmd <pid> VM.set_flag -XX:NewSize=512m
jcmd <pid> VM.set_flag -XX:MaxNewSize=512m

# 强制启动Full GC回收老年代(慎用)
jcmd <pid> GC.run

优化验证流程

  1. 使用 JMH 做GC压力测试
  2. 对比优化前后jstat的YGC频率下降比例
  3. 通过APM工具(Arthas)观察业务TPS波动

通过以上方法,通常可将YGC频率降低50%-90%。若仍存在异常,需要结合具体业务代码进行内存分配路径分析。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 深入了解Spring中getBean()的五种方式

    深入了解Spring中getBean()的五种方式

    在本文中,我们将详细介绍从BeanFactory中获取bean的多种方式。简单地说,正如方法的名称所表达的,getBean()负责从Spring IOC容器中获取bean实例,希望对大家有所帮助
    2023-02-02
  • Java常用时间工具类总结(珍藏版)

    Java常用时间工具类总结(珍藏版)

    这篇文章主要为大家详细介绍了Java中一些常用时间工具类的使用示例代码,文中的代码简洁易懂,对我们学习Java有一定帮助,需要的可以参考一下
    2022-07-07
  • SpringBoot+VUE实现数据表格的实战

    SpringBoot+VUE实现数据表格的实战

    本文将使用VUE+SpringBoot+MybatisPlus,以前后端分离的形式来实现数据表格在前端的渲染,具有一定的参考价值,感兴趣的可以了解一下
    2021-08-08
  • 详解JAVA序列化及实际应用场景分析

    详解JAVA序列化及实际应用场景分析

    序列化就是将对象转换为可以存储或传输的形式,以实现对象持久化存储到磁盘中,或者在网络中传输,这篇文章介绍JAVA序列化及实际应用场景分析,感兴趣的朋友跟随小编一起看看吧
    2024-12-12
  • Spring Cloud中FeignClient实现文件上传功能

    Spring Cloud中FeignClient实现文件上传功能

    这篇文章主要为大家详细介绍了Spring Cloud中FeignClient实现文件上传功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-04-04
  • SpringBoot中熔断器的原理和使用详解

    SpringBoot中熔断器的原理和使用详解

    这篇文章主要介绍了SpringBoot中熔断器的原理和使用详解,熔断器是一种用于处理分布式系统中故障的设计模式,它可以防止出现故障的服务对整个系统造成连锁反应,需要的朋友可以参考下
    2023-07-07
  • java中tomcat的80端口被占用问题解决

    java中tomcat的80端口被占用问题解决

    java中tomcat的80端口被占用问题解决,需要的朋友可以参考一下
    2013-03-03
  • java如何用递归生成树形结构

    java如何用递归生成树形结构

    作者分享了自己在使用脚本之家资源进行编程时的经验,包括准备实体对象、测试数据、构造树形结构递归函数、测试以及输出结果等步骤,作者希望这些经验能对大家有所帮助,并鼓励大家支持脚本之家
    2025-03-03
  • 浅谈Java中GuavaCache返回Null的注意事项

    浅谈Java中GuavaCache返回Null的注意事项

    Guava在实际的Java后端项目中应用的场景还是比较多的,比如限流,缓存,容器操作之类的,本文主要介绍了GuavaCache返回Null的注意事项,感兴趣的可以了解一下
    2021-10-10
  • java实现文件上传的详细步骤

    java实现文件上传的详细步骤

    文件上传是用户将本地文件通过Web页面提交到服务器的过程,涉及客户端、服务器端、上传表单等组件,在SpringBoot中,通过MultipartFile接口处理上传文件,并将其保存在服务器,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-10-10

最新评论