【发布时间】:2023-04-05 05:37:01
【问题描述】:
我们有一个应用程序部署在 Tomcat 8 应用程序服务器上,当前监控服务器 (Zabbix) 配置为在堆内存使用率为 90% 时生成警报。
生成的某些警报提示我们进行堆转储分析。堆转储中没有任何结果,没有内存泄漏。有很多不可达的对象因为没有 GC 而没有被清理。
JVM 配置:
-Xms8192m -Xmx8192m -XX:PermSize=128M -XX:MaxPermSize=256m
-XX:+UseParallelGC -XX:NewRatio=3 -XX:+PrintGCDetails
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/app/apache-tomcat-8.0.33
-XX:ParallelGCThreads=2
-Xloggc:/app/apache-tomcat-8.0.33/logs/gc.log
-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps
-XX:+PrintGCTimeStamps -XX:GCLogFileSize=50m -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=30
我们尝试使用jcmd 命令手动运行垃圾收集,它清除了内存。运行jcmd后的GC日志:
2016-11-04T03:06:31.751-0400: 1974627.198: [Full GC (System.gc()) [PSYoungGen: 18528K->0K(2049024K)] [ParOldGen: 5750601K->25745K(6291456K)] 5769129K->25745K(8340480K), [Metaspace: 21786K->21592K(1069056K)], 0.1337369 secs] [Times: user=0.19 sys=0.00, real=0.14 secs]
问题:
- 上面是否有任何配置导致 GC 没有自动运行。
- 此行为的原因是什么?我知道Java会在需要时进行GC。但是,如果即使堆利用率为 90% 时它也没有运行 GC,那么警报阈值应该是多少(如果根据堆利用率发出任何警报是否有意义)。
【问题讨论】:
-
只是想知道:如果有一些“cron 作业”线程每天运行一次 System.gc() 会不会有意义?或者它会检查利用率并在您 > 80% 时运行 system.gc() ?
-
@GhostCat:可以这样做,但不推荐。 GC 永远不能被强制,只能被请求。此外,问题陈述不是关于当 jvm 没有自动运行时如何运行 gc。我想知道它为什么没有运行,它等待的阈值是多少。
-
我把它作为评论是有原因的。这更像是一个实验的建议。是的,有时一个人应该努力去理解一切。但有时这样做代价高昂,可以使用廉价的解决方法来代替。这就是我想说的......
-
一般来说,如果VM在任何堆空间中发生分配失败或达到占用阈值(在老年代空间中),就会触发GC。对于 CMS,该阈值是终身堆占用的initally > 90%。但这实际上取决于您使用的垃圾收集器、VM 版本和 VM 供应商。
-
@GhostCat:如果我试图解决问题,我会考虑解决方案。 90% 的堆利用率现在并没有受到影响。
标签: java garbage-collection jvm