java - 找到 GC overhead limit exceeded 异常来源的正确方法

标签 java garbage-collection

我有一个非常复杂的遗留代码。
不时地执行它,生成 java.lang.OutOfMemoryError : GC overhead limit exceeded

确定其来源的正确方法是什么?
代码非常复杂(多个 HashMap 、字符串操作等)

最佳答案

java.lang.OutOfMemoryError : GC overhead limit exceeded 是由于 GC 花费的 CPU 时间相对于在应用程序代码中花费的 CPU 时间量而言过多。

换句话说,GC 估计它没有取得足够的进展来保持应用程序以合理的吞吐量运行。

有3个可能的原因:

  • A) 一些代码创建了真正大量的对象,同时花费了相当少的 CPU 时间(因此 GC 时间超过了开销限制)
  • B) 您的堆太小了,您的应用程序恰好触发了达到开销限制而不是内存不足
  • C) 你有一个缓慢的内存泄漏并且 GC 正在耗尽呼吸空间并且恰好在它进入 内存不足 情况之前抛出 达到开销限制

要确定 A),您需要配置文件分配率。

B) 可以简单地通过提高堆限制来解决。

C) 与 B) 的不同之处在于它在增加堆大小后仍然会抛出。在那种情况下,您只需启用 -XX:+HeapDumpOnOutOfMemoryError 并分析转储中是否有泄漏的对象。

在少数情况下,启发式方法可能会被误导。在这些情况下,可以通过调整 -XX:GCTimeRatio= 来放宽限制以允许 GC 消耗更多的 CPU 时间,或者使用 -XX:-UseGCOverheadLimit 完全禁用它.但在大多数情况下,这只会延迟不可避免的内存不足 OOM。

关于java - 找到 GC overhead limit exceeded 异常来源的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30093290/

相关文章:

java - 在 h2o 中加载大于内存大小的数据

具有多个键的 Java WeakHashMap?

java - 使用 equals 比较字符

java - 如何使用 aries 蓝图将 apache karaf 包作为服务注入(inject)到 Web 应用程序中?

java - 用Lombok 1.18.12构建的Gradle 6.4不生成getter和setter

java - VarHandle 获取/设置不透明

解释器环境中的python垃圾收集和_下划线

java - Java 中 DirectByteBuffer 的堆内存占用是多少?

c# - 是c#中闭包中使用其字段时被闭包捕获的对象

java - JFace数据绑定(bind): Update model only if all validators succeed