我有一个非常复杂的遗留代码。
不时地执行它,生成 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/