繁体   English   中英

什么时候JVM抛出OutOfMemoryError

[英]When exactly is the JVM throwing an OutOfMemoryError

我们正在运行一个有时“冻结”的Java应用程序,因为某些线程几乎使用了所有堆。 尽管JVM执行Full GC持续时间超过60秒,但应用程序永远不会因OutOfMemoryError而死亡。

我从Java文档中读到:

如果花费太多时间进行垃圾收集,吞吐量收集器将抛出内存不足的异常。 例如,如果JVM花费超过总时间的98%进行垃圾收集并且正在恢复少于2%的堆,则会导致内存不足。

我想了解更多关于98%的时间意味着什么(时间框架是什么?)的信息,以及是否可以降低此值,即如果应用程序在GC中花费90%的时间而无法释放OOME超过10%的堆。

目标是确保应用程序将在OOME中死亡(而不是仅运行GC),因此我们可以在OOME上生成转储。

以下是我们使用的内存和GC设置(操作系统是Solaris):

-Xms2048m -Xmx2048m \
-Xmn512m \
-XX:PermSize=256m 
-XX:MaxPermSize=256m \
-XX:+UseParNewGC 
-XX:ParallelGCThreads=16 \
-XX:+UseConcMarkSweepGC 
-XX:+CMSParallelRemarkEnabled \
-XX:+DisableExplicitGC \
-XX:+PrintGC 
-XX:+PrintGCDetails 
-XX:+PrintGCTimeStamps \
-XX:+PrintClassHistogram \
-Xloggc:/gcmonitor.log \
-XX:+HandlePromotionFailure \
-XX:SurvivorRatio=4 
-XX:TargetSurvivorRatio=90 
-XX:MaxTenuringThreshold=10 \
-XX:+UseTLAB 
-XX:TLABSize=32k 
-XX:+ResizeTLAB \
-XX:+UseMPSS \

我想了解更多关于这98%的时间意味着什么的信息(时间范围是多少?)

回答这个问题: 超出GC开销限制表示它是1分钟。

可以降低此值

再次查看上面提到的问题,看起来你可以使用GCTimeLimitGCHeapFreeLimit参数。

如果您只是想强制OOM获得堆转储的附带好处,您现在可以随时在正在运行的Java进程上执行此操作:

找到过程:

jps -v

强制转储

jmap -dump:file = heap.bin

然后在您选择的工具中分析heap.bin。

在OOME或jmap上以交互方式进行堆转储可能导致JVM暂停几分钟。 使用gcore手动创建核心转储通常更有效,然后使用jmap从核心获取堆转储。

我会分配更多堆,看看是否有助于缓解问题。 还要注意过度的GC调整 - 通常收集器具有很好的默认值,如果您确定这些选项根据应用程序的对象分配/保留模式显着提高了GC性能,我只建议使用Xloggc之后的选项。 并行收集器线程也可能太高,具体取决于可用的硬件线程数。

您应该能够从GC日志确定堆使用的模式,并确定这是由单个线程快速利用,执行快速耗尽堆的操作,还是较慢的“泄漏”模式,其中许多对象被提升时间导致终身一代人争论,很少有候选人可以收集 - 直方图也会有所帮助。

所有这一切,专注于堆转储肯定是要走的路。 Eclipse MAT是最好的分析工具IMO。 如果您之前没有使用它,这里是一个很好的起点:

http://kohlerm.blogspot.com/2009/07/eclipse-memory-analyzer-10-useful.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM