java - JVM 堆已用百分比 - 何时生成警报

标签 java garbage-collection jvm

我们有一个部署在 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]

问题:

  1. 上面是否有任何配置导致 GC 未自动运行。
  2. 这种行为的原因是什么?我知道 Java 会在需要时进行 GC。但是,如果即使在堆利用率达到 90% 时它也没有运行 GC,警报阈值应该是多少(以及根据堆利用率发出任何警报是否有意义)。

最佳答案

垃圾收集器决定收集的时间因垃圾收集器而异。我还没有找到关于您的(并行 GC)垃圾收集器何时运行的任何硬性 promise 。许多垃圾收集器还调整几个不同的变量,这些变量会影响它何时运行。

正如您自己所注意到的,您的应用程序可以在堆使用率很高的情况下仍然运行良好。您在应用程序中寻找的是垃圾收集器仍然高效。这意味着它可以在一次运行中清理大量垃圾。

垃圾回收的一些方面

大多数垃圾收集器都有两种或多种策略,一种用于“年轻”对象,一种用于“旧”对象。当一个年轻的对象在最新的(几次)收集中还没有被收集到时,它就变成了一个老对象。这背后的想法是,如果一个对象还没有被收集,那么下次它也可能不会被收集。 (大多数对象要么生命周期很短,要么生命周期很长)。垃圾收集器对年轻对象进行了非常有效但不完美的清理。当这不能释放足够的数据时,就会对所有(新旧)对象进行更昂贵的垃圾收集。

这通常会产生锯齿(取自 site ): Heap size over time 在这里,您会看到堆大小有许多小的下降,并且堆在缓慢增长。时不时做一个大的 Collection ,有一个大的掉落。实际“使用”的内存是大集合后剩余的内存量。

衡量方面

这导致您在确定应用程序的健康状况时可以查看以下方面:

  1. 您的应用程序垃圾收集所花费的时间(总时间和占 CPU 时间的百分比)。
  2. 垃圾收集后可用的内存量。
  3. 大型垃圾收集的数量快速增加。

在大多数情况下,您需要监控应用程序在负载下的行为,以了解哪些值对您有利。

并行垃圾收集器使用 similar condition确定一切是否还好:

If more than 98% of the total time is spent in garbage collection and less than 2% of the heap is recovered, then an OutOfMemoryError is thrown.

您可以使用 VisualVM 和 Jconsole 清楚地看到所有这些统计数据。我不确定您可以在监控工具中使用哪个作为触发器

关于java - JVM 堆已用百分比 - 何时生成警报,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40420074/

相关文章:

java - apache hub - 桌面应用程序

java - 将列表收集到 Java 8 中的 Map<Object1 , Map<Object2, Object3>> 中

java - 如何强制 HTTP Listener Connector 成为一种方式?

java - InputStreams 被 GCed

python - Python 中的 MemoryView 和垃圾收集

java - Apache Beam 执行

java - JVM 如何确保跨所有处理器架构的平台独立性?

java - JVM 如何处理 RuntimeException(s)

java - JVM G1 survivor 空间容量为0

java - 在 setter/getter 中创建新对象,确保它不位于虚拟机中