在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配置参数 .
我的问题是当我分析由于 OutOfMemoryException
使用Eclipse Memory Analyzer创建的堆转储时,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 回答
您使用的是哪种GC?你可能错过了伊甸园,试着用jstat - Java Virtual Machine Statistics Monitoring Tool
这并不一定意味着你的堆已满,请参阅this Q&A
这并不意味着你的堆剩下0个字节,这意味着无法满足分配请求 . 如果某些东西试图分配600MB并且只剩下500MB那么就会抛出一个OOME .
获取堆栈跟踪以查看执行相关分配的呼叫站点是否可以执行任何可疑操作将是一个开始 . 或者您可以尝试碰撞堆大小,看看问题是否消失 .