Java堆转储表示在OutOfMemory异常之后,使用的堆大小比实际堆定义小30%



JVM抛出OutOfMemory异常后,我正在分析一些堆转储。我在Windows2008R2平台上使用HotspotJDK1.7(64位)。应用程序服务器是JBoss 4.2.1GA,通过Tanuki Java Service Wrapper启动。

它以以下参数启动:

wrapper.java.additional.2=-XX:MaxPermSize=256m
wrapper.java.initmemory=1498
wrapper.java.maxmemory=3000
wrapper.java.additional.19=-XX:+HeapDumpOnOutOfMemoryError

翻译为:

-Xms1498m-Xmx3000m-XX:MaxPermSize=256m-XX:+HeapDumpOnOutOfMemoryError

还有一些其他的GC&JMX配置参数。

我的问题是,当我使用Eclipse内存分析器分析由OutOfMemoryException创建的堆转储时,MAT总是显示2.3G或2.4G的堆大小。我已经在MAT中启用了Keep Unreachable Objects选项,所以我不认为MAT在修剪堆。

java.lang.RuntimeException: java.lang.OutOfMemoryError: GC overhead limit exceeded

java.lang.OutOfMemoryError: Java heap space

MAT:总结

Size: 2.3 GB Classes: 21.7k Objects: 47.6m Class Loader: 5.2k

我的实际堆文件大小大约是3300KB,所以它们与我的3000m最大堆大小设置一致。

那么MAT中缺失的500-600M内存在哪里呢?为什么MAT只显示我的堆大小为2.4G?

SO上的其他帖子倾向于表明JVM在转储堆之前进行了一些GC,但如果缺少的500M是由于GC造成的,那么为什么它一开始就抛出OOM呢?如果GC实际上可以清除500M(或我的堆的近25%),那么JVM真的内存不足吗?

有没有办法调整堆转储,这样我就可以获得堆的完整图片(包括丢失的500M)?

如果没有,我发现我真的很难找到我是如何/为什么会遇到这些OOM的。

根据某人的请求,我正在附加来自活动节点的jstat -gc <PID> 1000的输出:http://pastebin.com/07KMG1tr.

您正在使用哪个GC?你可能错过了伊甸园,试着使用jstat-Java虚拟机统计监控工具

java.lang.OutOfMemoryError:GC开销限制超过

这并不一定意味着你的堆已经满了,请参阅这个问答;

java.lang.OutOfMemoryError:java堆空间

,这并不意味着您的堆还剩0个字节,而是意味着无法满足分配请求。如果有东西试图分配600MB,而只剩下500MB,那么就会抛出OOME。

如果没有,我会发现我真的很难找到如何/为什么会遇到这些OOM。

获取堆栈跟踪以查看进行有问题分配的调用站点是否做了任何可疑的事情将是一个开始。或者你可以试着改变堆的大小,看看问题是否消失了。

最新更新