JVM究竟在什么时候抛出一个OutOfMemoryError

2022-09-03 07:54:51

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

我从Java文档中读到:

如果执行垃圾回收花费的时间过多,吞吐量收集器将引发内存不足异常。例如,如果 JVM 花费的总时间超过 98% 的时间进行垃圾回收,并且恢复的堆少于 2%,则它将引发内存不足的预期。

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

目标是确保应用程序将使用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 \

答案 1

我想了解更多有关这98%时间意味着什么的信息(时间框架是什么?

回答此问题:超出 GC 开销限制表示为 1 分钟。

可以降低此值

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


答案 2

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

查找流程:

jps -v

强制转储

jmap -dump:file=heap.bin

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


推荐