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

时间:2016-11-04 10:14:24

标签: 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,那么应该是什么警报阈值(如果根据堆利用率获得任何警报甚至是有意义的话)。

1 个答案:

答案 0 :(得分:6)

当垃圾收集器决定收集每个垃圾收集器不同时。我的(并行GC)垃圾收集器运行时,我找不到任何硬性约定。许多垃圾收集器还会调整几个不同的变量,这些变量会影响它何时运行。

正如您已经注意到的那样,您的应用程序可能具有较高的堆使用率并仍然可以正常运行。您在应用程序中寻找的是垃圾收集器仍然有效。这意味着它可以在一次运行中清理大量垃圾。

垃圾收集的某些方面

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

这通常会产生锯齿(取自site): Heap size over time 在这里,您可以看到堆大小的许多小滴和缓慢增长的堆。每隔一段时间就会完成一个大型集合,并且有很大的下降。实际使用过的' memory是大量收集后剩余的内存量。

衡量方面

在确定应用程序的运行状况时,可以查看以下几个方面:

  1. 应用程序垃圾收集所花费的时间(总计和占CPU时间的百分比)。
  2. 垃圾收集后可用的内存量。
  3. 大型垃圾收集数量的快速增加。
  4. 在大多数情况下,您需要在负载下监控应用程序的行为,以查看适合您的值。

    并行垃圾收集器使用similar condition来确定是否所有内容仍然正常:

      

    如果超过98%的总时间花在垃圾收集上,并且回收的堆少于2%,则抛出OutOfMemoryError。

    使用VisualVM和Jconsole可以很好地看到所有这些统计信息。我不确定您可以在监控工具中使用哪个触发器