【问题标题】:Is it possible to get OutOfMemoryError because garbage collection too slow?是否有可能因为垃圾收集太慢而导致 OutOfMemoryError?
【发布时间】:2012-01-03 21:47:30
【问题描述】:

在 java 中,是否有可能出现 OutOfMemoryError 异常,即使应该有足够的内存应该垃圾回收释放更多内存?也就是说,如果没有足够的内存分配,gc会在抛出OutOfMemoryError之前强制运行吗?

谢谢。

【问题讨论】:

  • 很好的问题,但是 AFAIK 没有办法通过设置任何参数来加速 GC,除了在代码中标记对 null 的引用。

标签: java garbage-collection out-of-memory


【解决方案1】:

一种情况,你可能会得到一个既不与堆相关也不与地址空间相关的 OOM:它是当 JVM 决定 GC 需要太多时间来运行时。

here

换句话说,你原来的问题,即“如果没有足够的内存分配,gc 是否会在抛出 OutOfMemoryError 之前强制运行”的答案是肯定的。

(您将从上面的链接中看到,gc/running 代码的比率为 98%/2%,这已经非常高了)

(注 2:这是针对 Sun 的/Oracle 的 JVM,不知道其他实现)

【讨论】:

    【解决方案2】:

    如果 GC 花费太多时间尝试释放内存并且没有释放太多内存,则可以通过这样做'java.lang.OutOfMemoryError:GC 开销限制超出'来获取它,请参阅this question

    【讨论】:

      【解决方案3】:

      GC 在 OutOfMemoryError 被抛出之前被强制运行。如果 JVM 实现了多种 GC(例如“并发”或“部分”),则会在 JVM 放弃之前运行“stop the world”GC,因此已尽一切可能避免错误。

      被引用的例外情况是,如果 GC 反复运行并且只恢复了极少量的存储空间(并且堆大小无法进一步扩展),那么它将认输,而不是继续以“爬行”模式运行。理论上,对于这种情况,稍微增加堆大小可以让“好”的应用程序运行正常,但是缓慢消耗堆的应用程序(这并不罕见)不会从堆的轻微增加中受益,并且会遇到同样的失败只是稍晚一点。

      [需要注意的是,在 GC 运行过于频繁的情况下,增加堆大小可能会显着降低 GC 开销,如果应用程序表现良好并且只是巧合地恰好在堆限制附近运行。 (当然,将堆大小增加到大于可用 RAM 通常会使应用程序运行速度变慢。)]

      【讨论】:

        【解决方案4】:

        GC通常会在OutOfMemoryError 被抛出之前尝试寻找内存,但是非常偶尔我见过一些可重复的例子,其中垃圾收集器不能完全保持向上,并且调用System.gc() 可以防止异常。

        这是一个非常例外(不是双关语)而不是规则 - 你应该几乎永远不要尝试自己引发垃圾收集。

        【讨论】:

          【解决方案5】:

          似乎如果您编写适当的代码,您将永远不会遇到 OOM。因为JVM会在遇到OOM之前运行gc。

          因此,如果您遇到 OOM,则很可能您的代码出现了一些内存泄漏。 检查一下。

          http://www.ibm.com/developerworks/library/j-leaks/

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-01-19
            • 2021-02-20
            • 1970-01-01
            • 1970-01-01
            • 2016-05-23
            • 1970-01-01
            相关资源
            最近更新 更多