java gc 时间过长_关于垃圾收集:“java.lang.OutOfMemoryError:超出GC开销限制”时GC时间过长的持续时间...

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

The parallel collector will throw an OutOfMemoryError if too much time is

being spent in garbage collection: if more than 98% of the total time is

spent in garbage collection and less than 2% of the heap is recovered, an

OutOfMemoryError will be thrown. This feature is designed to prevent

applications from running for an extended period of time while making

little or no progress because the heap is too small. If necessary, this

feature can be disabled by adding the option -XX:-UseGCOverheadLimit to the

command line.

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

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

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

从文档来看,似乎是整个2周的98%。 您是否使用以下标志启用了GC日志-verbose:gc -XX:+ PrintGCDetails XX:+ PrintGCTimeStamps -Xloggc:PATH_FROM_ROOT / gclog.log。 很高兴看到应用程序运行时间和停止时间由于GC。

GC记录是一个很好的建议,我会尝试。 2周98%似乎不太可能,但你是对的,这就是文档所暗示的。 我希望这只是不精确的写作

你有没有找到98%的时间含义? 我的观点是GC应该在异常发生的那一刻忙于占用应用程序利用率的98%而不是2周。

@Monis:我还没找到,放弃了看。 98%的时间"在当下"没有多大意义,因为根据定义,时刻不是一段时间,所以"98%的时刻"也不可能(并且就像"长时间"一样 2%的时刻)。

I'm trying to determine a best approach to actually solving this issue rather than just using -XX:-UseGCOverheadLimit but I feel a need to better understand the issue I'm solving.

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

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

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

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

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

我正在尝试一些分析,我也会尝试一下。 谢谢。

我和你一样走了一条路,试验参数。 最终,增加堆大小和我的代码的一些调整(我发现没有内存泄漏)似乎已经解决了我的问题。

为什么你会在批量风格的应用程序中使用CMS或G1? 吞吐量收集器不是更好吗?

But 98% of what time? 98% of the entire two weeks the application has been running? 98% of the last millisecond?

简单的答案是它没有指定。然而,在实践中启发式"有效",所以它不能是你提出的两种极端解释中的任何一种。

如果您真的想知道测量的间隔是什么,您可以随时阅读OpenJDK 6或7源代码。但我不会打扰,因为它不会帮助你解决问题。

"最佳"方法是对调优进行一些阅读(从Oracle / Sun页面开始),然后仔细"旋转调整旋钮"。它不是很科学,但考虑到目前可用的工具,问题空间(准确预测应用程序+ GC性能)"太难"了。

> 98%将在同一时间段内测量,其中少于2%的内存被恢复。

很可能没有固定的时间段。例如,如果在每1,000,000个对象实时检查之后进行OOM检查。花费的时间取决于机器。

您很可能无法通过添加-XX:-UseGCOverheadLimit来"解决"您的问题。最可能的结果是您的应用程序将慢慢爬行,使用更多的内存,然后达到GC根本不再恢复任何内存的程度。相反,修复内存泄漏,然后(如果仍然需要)增加堆大小。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值