"java.lang.OutOfMemoryError:超出GC开销限制"中过多GC时间的持续时间

jil*_*wit 10 java garbage-collection out-of-memory

偶尔,在每两天一次到每两周一次之间,我的应用程序在代码中看似随机的位置崩溃:java.lang.OutOfMemoryError: GC overhead limit exceeded.如果我谷歌这个错误,我来到这个问题,并引导我到这个阳光文件,它表示:

如果在垃圾收集中花费了太多时间,并行收集器将抛出OutOfMemoryError:如果在垃圾收集中花费了超过98%的总时间并且恢复了少于2%的堆,则将抛出OutOfMemoryError.此功能旨在防止应用程序长时间运行,同时由于堆太小而很少或没有进度.如有必要,可以通过在命令行中添加选项-XX:-UseGCOverheadLimit来禁用此功能.

这告诉我,我的应用程序显然占用了垃圾收集总时间的98%,只能恢复2%的堆.

但98%的时间是什么时候?应用程序运行的整个两周的98%?最后一毫秒的98%?

我正在尝试确定一个实际解决这个问题的最佳方法,而不仅仅是使用,-XX:-UseGCOverheadLimit但我觉得需要更好地理解我正在解决的问题.

gus*_*afc 6

我正在尝试确定一个实际解决这个问题的最佳方法,而不仅仅是使用,-XX:-UseGCOverheadLimit但我觉得需要更好地理解我正在解决的问题.

好吧,你使用了太多的内存 - 从它的声音来看,这可能是因为内存泄漏缓慢.

您可以尝试使用增加堆大小-Xmx,如果这不是内存泄漏,但有迹象表明您的应用实际上需要大量堆并且您当前具有的设置略微低,这将有所帮助.如果是内存泄漏,这只会推迟不可避免的事情.

要调查它是否是内存泄漏,请指示VM使用该-XX:+HeapDumpOnOutOfMemoryError开关在OOM上转储堆,然后分析堆转储以查看是否存在比应有的更多对象.http://blogs.oracle.com/alanb/entry/heap_dumps_are_back_with是一个非常好的起点.


编辑:由于命运会有它,我碰巧在问这个问题的一天后,在批量风格的应用程序中遇到了这个问题.这不是由内存泄漏引起的,并且增加堆大小也没有帮助.我所做的实际上是减少堆大小(从1GB到256MB)以使更快的GC(尽管更频繁).YMMV,但它值得一试.

编辑2:小堆没有解决所有问题......下一步是启用G1垃圾收集器,它似乎比CMS做得更好.