记一次生产系统每隔10小时(36000000毫秒)固定进行一次Full GC排查思路

一、 背景描述

某个应用在生产环境通过系统监控发现,应用每隔10小时就会触发一次Full GC,该系统当时承接的业务量并不大,而且固定10小时就会进行Full GC,通过监控时间轴发现Full GC频率很规律,直觉告诉我这不是JVM自身触发的Full GC操作,应该是某个定时任务中进行了垃圾回收操作,但是什么业务场景会存在这种情况呢?

二、问题排查

通过在测试环境上通过系统监控可以发现,应用的JVM使用情况并未达到Full GC条件,是系统调用了System.gc()方法产生的Full GC。于是,我在代码中对System.gc()方法调用进行了搜索,甚至为了防止是通过反射方式调用的,还检索了所有业务代码,但是均未发现有业务代码进行该方法的调用。

不过,在排查过程中,Jdk中有一个GC类却引起了我的注意:

在这里插入图片描述
在Java中Daemon一般用作标识守护线程,这里有一个Daemon类,是不是因为在这个线程类中调用System.gc()方法的原因呢?

查看sun.misc.GC.Daemon类的源码:

在这里插入图片描述

通过源码可以发现,Daemon类继承了Thread线程类,并且有调用System.gc()方法。

同时,在应用中,通过jstack命令查看,应用中确实有此线程运行:

在这里插入图片描述

通过对代码进行断点调试,发现Apache cxf相关类会有周期性Full GC的问题,我引入的相关依赖如下:

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
            <version>3.3.11</version>
        </dependency>

通过对源码解析发现,最终调用的情况如下:

  • org.apache.cxf.common.logging.LogUtils
    在这里插入图片描述
  • org.apache.cxf.common.logging.JDKBugHacks
    在这里插入图片描述
    注意这里:skipHack()方法的判断逻辑,通过这部分代码可以设置参数跳过执行创建守护线程的逻辑。
    在这里插入图片描述

三、原因分析

源码解析流程如下:LogUtils类加载时会通过静态代码块调用JDKBugHacks.doHacks()方法,此方法会获取系统环境变量org.apache.cxf.JDKBugHacks.gcRequestLatency,如果没有设置,默认为false,此时会通过反射调用sun.misc.GCrequestLatency方法,

在这里插入图片描述
初始化的时候deamon对象的值为null,此时会调用Daemon.create()方法,如下:

在这里插入图片描述
create() 方法中,会创建一个名字为 GC Daemon的守护线程,如下:

在这里插入图片描述

四、问题解决

Apache CXF是一个开源的Service框架,它实现了JCP和Web Servicez中的一些重要标准,大大简化了Web Service服务构建开发工作,通过上述对org.apache.cxf.common.logging.JDKBugHacks源码分析,可以在项目启动脚本中加入

-Dorg.apache.cxf.JDKBugHacks.gcRequestLatency=true

来跳过创建守护线程的逻辑,解决固定Full GC的逻辑。

<think>好的,我现在需要回答用户关于G1垃圾回收器中Eden区每分钟进行一次垃圾回收是否频率过高的问题。首先,我需要回忆G1垃圾回收器的基本机制,特别是关于Eden区和Minor GC的部分。 根据引用[1],年轻代(Young Generation)是所有新对象创建的地方,当年轻代填满时,会执行垃圾回收,称为Minor GC。年轻代分为Eden区和两个Survivor区。在G1中,虽然内存布局与传统收集器不同,但Minor GC的触发条件仍然是Eden区满。因此,Eden区的GC频率直接取决于对象的分配速率和Eden区的大小。 用户提到每分钟一次,是否过高?我需要考虑正常情况下的Minor GC频率。一般来说,Minor GC的频率取决于应用的对象分配速率。高频率的GC(如几秒一次)可能导致性能问题,但每分钟一次可能属于较低频率。不过,是否“过高”还需结合具体场景。比如,如果应用对延迟敏感,即使每分钟一次也可能需要优化;若应用吞吐量优先,且暂停时间在可接受范围内,则可能正常。 接下来,需要分析可能的原因。引用[2]提到G1的参数设置,比如-XX:G1MixedGCCountTarget,这可能影响混合GC的频率,但主要影响老年代回收。而Eden区的Minor GC频率更多由Eden大小和分配速率决定。如果Eden区过小或对象分配过快,会导致频繁GC。用户的情况是每分钟一次,可能Eden区较大或分配速率较低,但需要检查。 另外,引用[4]提到G1的Full GC可能导致长时间停顿,但用户的问题是关于Minor GC的。不过,如果Eden区GC频繁,可能导致晋升到老年代的对象增多,从而触发Mixed GCFull GC,间接影响整体性能。需要综合考虑这些因素。 如何判断当前情况是否正常?可以使用jstat工具,如引用[3]提到的jstat -gcutil,监控GC统计信息。查看YGC(Young GC次数)和时间间隔,计算频率。如果YGC每分钟一次,且每次暂停时间很短(如几十毫秒),则可能正常。若暂停时间较长或存在其他问题(如内存泄漏),则需要调整。 可能的优化措施包括调整Eden区大小(通过-XX:InitialHeapSize、-XX:MaxHeapSize等参数),或优化应用代码减少对象分配。同时,确保堆大小足够,避免频繁扩容或收缩。 总结:每分钟一次Minor GC不一定过高,需结合暂停时间、吞吐量、应用需求来判断。建议监控GC日志,分析具体数据后再决定是否需要优化。</think>关于G1垃圾回收器中Eden区每分钟进行一次垃圾回收的频率是否过高,需结合具体场景和性能指标分析: ### 1. **G1的Minor GC机制** G1的Eden区垃圾回收(Minor GC)触发条件是**Eden区空间耗尽**,其频率由以下因素决定: - **Eden区大小**:通过参数$ -XX:G1NewSizePercent $(默认5%)和$ -XX:G1MaxNewSizePercent $(默认60%)动态调整,堆内存越大,Eden区容量可能越高,Minor GC间隔越长[^1]。 - **对象分配速率**:若应用创建对象速度较快,Eden区填满更快,Minor GC更频繁。 ### 2. **评估频率合理性** - **典型场景**:对于多数应用,**几秒到几分钟**触发一次Minor GC均属正常。若每次暂停时间(如$ YGCT $)在**10-200毫秒**内且不影响业务,则无需优化[^3]。 - **过高标准**:若Minor GC导致**吞吐量下降**(如CPU利用率低于70%)或**响应时间波动**,则需调整。例如引用[4]中Full GC暂停100秒明显异常,但Minor GC每分钟一次若未伴随性能劣化则可能合理。 ### 3. **诊断与优化方法** - **监控数据**:通过`jstat -gcutil <pid> 1000`观察`YGC`(Young GC次数)和`YGCT`(Young GC总时间),计算实际频率与耗时。 ```bash jstat -gcutil 12345 1000 # 每1秒采样一次进程12345的GC状态 ``` - **调整Eden区**:若需降低频率,可**增大堆内存**或**提高Eden占比**: ```bash -XX:InitialHeapSize=4g -XX:MaxHeapSize=4g -XX:G1MaxNewSizePercent=40 ``` - **优化对象分配**:减少短生命周期对象创建,例如复用对象或使用本地缓存。 ### 4. **关联问题排查** - **晋升速率**:若对象过快晋升到老年代(观察`ParOldGen`使用率),可能引发Mixed GC,需检查`-XX:MaxTenuringThreshold`(晋升年龄阈值)。 - **Full GC触发**:若老年代无法容纳晋升对象,会触发Full GC,此时需优化老年代回收策略[^2]。 ### 结论 **若满足以下条件,每分钟一次Minor GC无需干预**: - 单次暂停时间 < 200毫秒 - 系统吞吐量(如QPS)达标 - 无Full GC或Mixed GC异常增加 否则需通过**调整Eden区大小**或**优化代码**降低频率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coder-文小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值