Java HeapDumps指示在OutOfMemory异常

时间:2016-06-06 14:42:27

标签: java garbage-collection jvm heap-dump eclipse-memory-analyzer

在JVM抛出OutOfMemory个异常后,我正在分析一些堆转储。我在Windows 2008R2平台上使用Hotspot JDK 1.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 Memory Analyzer分析由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

2 个答案:

答案 0 :(得分:1)

您使用的是哪种GC? 您可能错过了Eden,尝试使用jstat - Java Virtual Machine Statistics Monitoring Tool

答案 1 :(得分:1)

  

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

这并不一定意味着您的堆已满,请参阅this Q&A

  

java.lang.OutOfMemoryError:Java堆空间

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

  

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

获取堆栈跟踪以查看执行相关分配的呼叫站点是否有任何可疑之处将是一个开始。或者您可以尝试碰撞堆大小,看看问题是否消失。