以编程方式捕获 Full GC 计数

btz*_*btz 5 java garbage-collection jvm

我正在尝试捕获在我们的 Java 应用程序中发生的完整 GC。到目前为止,我有两种方法,都有缺陷:

  1. 每 x 秒轮询一次 GarbageCollectorMXBean 对象,然后尝试提取自上次轮询以来的 GC 时间和 GC 计数,并尝试检测 GC 发生的时间。不幸的是,我们不知道它是否是 Full GC。
  2. 使用 javax.management.NotificationListener,订阅 GarbageCollectorMXBean 通知。理论上,当 GC 发生时,应用程序将收到通知,文本“主要 GC 结束”和“次要 GC 结束”以及原因。这种方法的缺陷是持续时间似乎非常不正确(有时显示 898 秒,而 GC 日志显示 0.2 秒),并且有一个神秘的情况“No GC”,这似乎表明实际上没有执行 GC(如gc 日志中没有条目)。

当我收到 GC 通知时,可以查询 GC MXBeans,然后检查是否已执行 GC 的混合方法是可能的。这样做的缺点是 No GC 原因可能仍会在“主要 GC”结束时触发,并导致逻辑更加复杂。

我真正想要的是应用程序由于 GC 操作而暂停的总时间。我认为捕获完整的 GC 将足以表明应用程序已经停止了一段时间,因此如果我们检测到频繁的 GC,我们知道有大量使用或应用程序将很快耗尽内存。是否有更好的解决方案来检测 GC 时间以及是否有完整的 GC?

编辑:明确地说,我想在给定的 JVM 中捕获此信息。这个 JVM 由一个单独的团队控制,我们没有必要控制他们将设置的 JVM 参数,我们只能提出建议。这个想法类似于飞行记录器,但它是向管理员实时提供信息。

eck*_*kes 2

如果你使用热点特定的GC beans,那么你可以区分new/old,而不是concurrent/full。但这在大多数情况下就足够了。

#LastGCInfo在这种情况下,我将进行轮询,并使用相关一代的之前/之后信息:

例如ParallelOld启用时的java.lang:type=GarbageCollector,name=PS Scavenge年轻代和java.lang:type=GarbageCollector,name=PS MarkSweep年老代。

使用 CMS,您可以看到并发集合和完整集合java.lang:type=GarbageCollector,name=ConcurrentMarkSweep(但希望永远不会有完整集合:)

这是 GC 和 VM 特定的,因此需要一些启发式方法来支持您关心的所有平台。

我认为只有使用飞行记录器事件才能进行更细粒度的监控,但我没有这方面的经验。