堆内存使用中的PS Old Gen内存:Java内存溢出异常的GC设置

12

输入图像描述

以下是我的JVM设置:

 JAVA_OPTS=-server -Xms2G -Xmx2G -XX:MaxPermSize=512M -Dsun.rmi.dgc.client.gcInterval=1200000 -Dsun.rmi.dgc.server.gcInterval=1200000 -XX:+UseParallelOldGC -XX:ParallelGCThreads=2 -XX:+UseCompressedOops  -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jbos88,server=y,suspend=n
问题: 总堆内存:2GB 老年代:1.4GB(堆的2/3) 新生代:600MB(堆的1/3)
老年代内存超过其分配大小的70%,即使达到100%(即1.4GB),也不被GC处理。如下图所示,它的内存使用率持续高峰,并且从未被GC。在JConsole中强制进行GC时,内存下降。这个问题最终会导致Web服务器崩溃。
我是否错过了什么或错误地设置了JVM?
谢谢提前帮助。
更新我的问题:
堆分析后,看起来有状态会话bean是主要嫌疑人: enter image description here 我们有状态会话bean,它们保存由Hibernate辅助的持久性逻辑。

你是否看到了JVM终止并出现了“OutOfMemoryError Heap Space”?或者你期望旧生代GC提前运行? - jmj
3个回答

7
GC最终会被调用,但老年代几乎从不被调用(因为它非常慢)。 GC确实运行,但它首先只在新生代和幸存者代上运行,对于清理老年代有完全不同的算法,比新生代/幸存者代慢得多。
这些数字非常高,与新生代相比,老年代不应该达到如此之高的数字。 我猜测你的程序存在内存泄漏。
我只能猜测你的程序正在处理大文件,你可能保存了对它们的引用时间过长。

4
即使主要问题(内存泄漏)已经解决,如果您仍希望经常清除旧的生成,以获得频繁的小暂停,则可以尝试设置。
-XX:MaxGCPauseMillis=(time in millis)

这仅适用于并行收集器和自适应大小策略开启的情况。默认情况下,自适应大小策略是开启的,但如果您想显式指定此选项,可以使用。

-XX:+UseAdaptiveSizePolicy

或者你可以切换到CMS收集器,这里你可以使用

-XX:CMSInitiatingOccupancyFraction=(% value) 
-XX:+UseCMSInitiatingOccupancyOnly

当老年代达到一定比例时,收集老年代的更可靠方式是什么。


我尝试了这些JVM参数,显然垃圾回收器无法释放旧的代空间,并且每次恢复很少的内存时都会不断地尝试释放内存。 - amitsalyan
如果在进行完整垃圾回收后内存没有得到显著恢复,那么您的旧生代中就不是垃圾。在这种情况下,这可能是应用程序的内存占用。如果是这样,您应该考虑增加分配的总内存。假设有状态会话Bean是内存的主要占用者,则我会说内存占用大约等于(创建新会话的速率会话超时平均会话大小)。 - Tharanga Hewavithana
为什么不在进行优化(@Remove注释)后分享堆的另一份分析呢?这样我就能更好地了解情况。我很想看到jmap -histo:live <pid>的输出结果。 - Tharanga Hewavithana
更改会话Bean后,请附上jconsole...其中一个下降到0MB的,请忽略,我已经重新启动了服务器... - amitsalyan

3

在这里输入图片描述有状态的会话Bean导致JVM内存不足。使用@Remove注释来明确处理它们可以解决这个问题。


9
你是怎么发现它的? - Nageswaran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接