Java Flight Recorder的GC统计与GC日志不符,求排查建议
为什么Java Mission Control的GC统计比GCViewer少?
这事儿我碰到过好几次,大概率是这几个原因导致的,咱们一步步捋:
1. 自定义JFR配置遗漏了部分GC事件
你用了settings=customSetting这个自定义配置,这很可能是核心问题。JFR的事件记录是靠配置文件(.jfc)来控制的,如果你的customSetting没有启用所有GC相关事件,或者给某些事件设置了过高的时间阈值,就会导致部分GC没被记录。
比如默认的profile.jfc模板只记录Full GC,而Young GC这类高频但耗时短的GC会被过滤掉。如果你的customSetting是基于profile模板改的,没调整GC事件的配置,自然就看不到所有GC了。
排查方法:
打开你的customSetting.jfc文件,检查以下几个关键事件的配置:
<!-- 检查Young GC事件是否启用且阈值为0(记录所有事件) --> <event name="jdk.GCYoungGeneration"> <setting name="enabled">true</setting> <setting name="threshold">0 ms</setting> </event> <!-- 检查Old GC事件 --> <event name="jdk.GCOldGeneration"> <setting name="enabled">true</setting> <setting name="threshold">0 ms</setting> </event> <!-- 检查Full GC事件 --> <event name="jdk.GCFull"> <setting name="enabled">true</setting> <setting name="threshold">0 ms</setting> </event>
如果这些事件没启用,或者阈值大于0,就会漏掉对应的GC。
2. JFR启动参数的补充配置
如果不想修改.jfc文件,也可以直接在启动参数里强制开启所有GC事件的记录,比如:
-XX:StartFlightRecording=defaultrecording=true,settings=customSetting, \ event=jdk.GCYoungGeneration#enabled=true,event=jdk.GCYoungGeneration#threshold=0, \ event=jdk.GCOldGeneration#enabled=true,event=jdk.GCOldGeneration#threshold=0, \ event=jdk.GCFull#enabled=true,event=jdk.GCFull#threshold=0
这样能确保JFR捕获所有类型的GC,不管耗时长短。
3. JMC视图默认过滤了部分GC事件
有时候不是JFR没记录,而是JMC的默认视图把某些GC藏起来了。比如在JMC的「GC统计」页面,默认可能只显示Full GC,需要手动调整过滤选项:
- 打开JMC的「GC」标签页
- 点击右上角的「View Options」或「Filters」按钮
- 确保「Young GC」「Old GC」「Full GC」都被勾选,没有被过滤
4. 极端情况:GC事件太短暂被JFR忽略
虽然概率很低,但如果某些GC的持续时间远低于JFR的采样精度(比如几微秒),JFR可能无法捕获到这类事件。不过这种情况在实际业务中很少见,因为哪怕是Young GC也至少会有几毫秒的停顿。
总结排查步骤:
- 先检查customSetting.jfc的GC事件配置,确保全量启用
- 调整JFR启动参数,强制开启所有GC事件的记录
- 在JMC中检查视图过滤设置,确认没有隐藏GC类型
按这个顺序排查,基本就能解决JMC统计和GCViewer不一致的问题了。
内容的提问来源于stack exchange,提问作者caffeine_inquisitor
相关产品推荐
相关产品推荐

