【发布时间】:2016-10-06 05:34:10
【问题描述】:
在 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。
【问题讨论】:
-
MAT 只打印一个存储在堆转储文件头中的数字。这个数字并没有说明转储文件中对象图的完整性。
标签: java garbage-collection jvm heap-dump eclipse-memory-analyzer