【问题标题】:Glassfish DAS OutOfMemory with total heap usage below max heap sizeGlassfish DAS OutOfMemory,总堆使用量低于最大堆大小
【发布时间】:2012-04-02 08:50:10
【问题描述】:

我在 Glassfish V2.1 6 实例集群配置(SLES 10 SP4,64 位 Suse Linux 机器,19Gb RAM)中运行大型企业应用程序,DAS 机器 server.log 显示一些“java.lang .OutOfMemoryError:Java 堆空间”错误。来自 DAS 的 jvm.log 的堆使用情况报告显示:

Heap
 PSYoungGen      total 103488K, used 99840K [0x00002aab237c0000, 0x00002aab2a270000, 0x00002aab4e260000)
  eden space 99840K, 100% used [0x00002aab237c0000,0x00002aab29940000,0x00002aab29940000)
  from space 3648K, 0% used [0x00002aab29940000,0x00002aab29940000,0x00002aab29cd0000)
  to   space 4672K, 0% used [0x00002aab29de0000,0x00002aab29de0000,0x00002aab2a270000)
 PSOldGen        total 1398144K, used 1398143K [0x00002aaace260000, 0x00002aab237c0000, 0x00002aab237c0000)
  object space 1398144K, 99% used [0x00002aaace260000,0x00002aab237bfe70,0x00002aab237c0000)
 PSPermGen       total 107200K, used 106931K [0x00002aaaae260000, 0x00002aaab4b10000, 0x00002aaace260000)
  object space 107200K, 99% used [0x00002aaaae260000,0x00002aaab4accd98,0x00002aaab4b10000)

从上面我们得到 1.6Gb (103488 + 1398144 + 107200 = 1608832 ~ 1.6Gb) 的总堆空间,即使允许的最大堆空间设置为 2Gb (-XX:MaxPermSize=512m -Xmx2048m)。那么我的问题是:为什么 JVM 在输出 OOM 错误之前不增加堆大小?我们如何解释上述堆报告?我在二进制堆文件上运行了 MAT 工具,发现了 2 个泄漏嫌疑人:

Problem suspect #1

One instance of "com.sun.jmx.mbeanserver.JmxMBeanServer" loaded by "<system class loader>" occupies 522,351,680 (34.12%) bytes. The instance is referenced by org.jvnet.glassfish.comms.admin.management.extensions.config.OverloadProtectionServiceConfigImpl @ 0x2aaacfe74ed0 , loaded by "com.sun.appserv.server.util.ASURLClassLoader @ 0x2aaace7fc630". The memory is accumulated in one instance of "java.util.HashMap$Entry[]" loaded by "<system class loader>".

Keywords
java.util.HashMap$Entry[]
com.sun.appserv.server.util.ASURLClassLoader @ 0x2aaace7fc630
com.sun.jmx.mbeanserver.JmxMBeanServer

Problem suspect #2

140,421 instances of "net.jxta.impl.endpoint.tcp.TcpMessenger", loaded by "com.sun.appserv.server.util.ASURLClassLoader @ 0x2aaace7fc630" occupy 735,809,464 (48.07%) bytes. These instances are referenced from one instance of "java.util.TimerTask[]", loaded by "<system class loader>"

Keywords
java.util.TimerTask[]
com.sun.appserv.server.util.ASURLClassLoader @ 0x2aaace7fc630
net.jxta.impl.endpoint.tcp.TcpMessenger

不幸的是,该错误发生在几周前,此后机器已重新启动,因此我可能丢失了一些上下文信息。我正在寻找提示或解释,并试图防止这些错误。提前感谢您的帮助。

干杯

/山姆

【问题讨论】:

  • 实际的OOM错误在哪里?看起来你更像是用完了 permgen 而不是堆内存。

标签: performance jvm glassfish out-of-memory heap-memory


【解决方案1】:

那么我的问题是:为什么 JVM 在输出 OOM 错误之前不增加堆大小?

使用您设置的 JVM 选项 (-Xmx2048m),最大堆空间将为 2G,没错,但您没有设置 初始堆空间选项 -Xms1024
此选项将告诉 JVM 最初为服务器提供 1024MB 堆空间,而不是在需要时缓慢增加。

这可能会阻止您收到 OOM 错误,因为有时 JVM 不会因为 GC 而注意到一些内存更改。

查看this 以优化您的应用程序服务器。

关于您的 MemLeaks:
很难判断这些是真正内存泄漏还是只是一些服务器类。
要检查这一点,您可以触发内存转储并对其进行分析,例如MemoryAnalyser

希望这有帮助,玩得开心!

【讨论】:

  • 我注意到,这个初始堆大小参数(-Xms)绝对应该设置(最大堆大小值恕我直言)。您发表的评论:“因为有时 JVM 不会注意到由于 GC 而发生的一些内存更改”,但我很担心。你有一些我可以研究的特定错误参考吗?我还注意到,已经为集群实例设置和调整了 GC 和堆相关的 JVM 选项,但仅部分在服务器 (DAS) 配置上。感谢您富有洞察力的回复。
  • 你的权利,-Xms 值应该设置为-Xmx 值。抱歉,目前我手头没有任何参考资料(只是一个关于 GC 在多次重新部署后未执行的错误跟踪器),但我可以推荐 thisthis 关于调整特别是垃圾收集的文章。他们帮助我在我的环境中解决了这个问题!干杯!
猜你喜欢
  • 2018-04-14
  • 2016-04-06
  • 2013-03-09
  • 2011-07-18
  • 2010-12-29
  • 1970-01-01
  • 2015-04-08
  • 2012-05-26
  • 2021-08-11
相关资源
最近更新 更多