JFR消耗内存过多,导致OOM

问题描述 投票:0回答:1

我们尝试在生产环境中启用 JFR(Java Flight Recorder)功能。我们使用以下启动参数:

-XX:StartFlightRecording=disk=true,dumponexit=true,name=profile_online,filename=/tmp/profile_`hostname`-`date +%Y_%m_%d_%H_%M_%S`.jfr,maxsize=4096m,maxage=2d,settings=/opt/app/WEB-INF/tars/prod/custom.jfc,path-to-gc-roots=false -XX:FlightRecorderOptions=maxchunksize=32m

我们使用的是 JDK 版本 11.0.14,使用的垃圾收集器是 G1。

在我们的一个应用程序上启用上述 JFR 配置后,四天后我们在 7 台机器上遇到了批量内存不足 (OOM) 问题。

我们查看了监控数据,发现堆情况显得比较正常。但是,我们注意到,在最近部署之前,mem rss 使用量约为 15GB(峰值为 16GB),部署后增加到约 15.5GB。

为了解决这个问题,我们尝试使用本机内存跟踪 (NMT) 进行分析,发现四天后,跟踪指标的内存开销已达到 400MB 左右。我们怀疑跟踪指标可能包括 JFR 的内存开销。

我们很困惑为什么部署后四天就出现批量 OOM 问题,以及 JFR 的内存消耗是否与运行时长有关。我们也很好奇 JFR 内存开销的主要来源以及是否有办法根据启动参数来估计 JFR 的内存开销。

java memory jvm out-of-memory jfr
1个回答
0
投票

JFR 似乎会填满内存,直到耗尽,除非您确保将录音转储到磁盘。 请注意,飞行记录数据不是从 Java 堆分配的,而是从系统内存分配的。 至少在 Java 21 中,即使您停止录制,该录制也将变得无法访问,并且仍然保留其正在使用的内存。

我通过使用

-XX:StartFlightRecording=disk=false,name=jfr
启动 Java 进程,然后运行
jcmd <PID> JfR.check
来确认录制正在进行中来对此进行测试。 让进程运行几个小时并且系统内存以恒定的速度消耗。然后
jcmd <PID> JFR.stop name=jfr
。 并且系统内存停止被消耗,但没有被释放。 此时运行
jcmd <PID> JfR.check
显示没有飞行记录。

要解决此问题,请安排一个任务定期运行以使用

jcmd <PID> JFR.dump

转储录音
© www.soinside.com 2019 - 2024. All rights reserved.