JVM超出了使用-Xmx定义的最大内存

我们有一个Java Web应用程序,我们从Java 1.5.0.19升级到Java 1.6.0.21

/usr/java/jdk1.6.0_21/bin/java -server -Xms2000m -Xmx3000m -XX:MaxPermSize=256m -Djava.awt.headless=true -Dwg.environment=production -Djava.io.tmpdir=/var/cache/jetty -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=31377 -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.ssl=false -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/webapp -Dprogram.name=run.sh -Djava.endorsed.dirs=/opt/3p/jboss/lib/endorsed -classpath /opt/3p/jboss/bin/run.jar:/usr/java/jdk1.6.0_21/lib/tools.jar org.jboss.Main -c default 

正如你所看到的,它应该预先分配2GB的堆,并且最大值为3GB(为什么我们预先分配这么多是因为这个应用程序很古老而且设计很差,所以有很多东西需要加载)。 我们在升级到1.6后最近看到的问题是,有时候内存会进入屋顶。 虽然内存使用可能是一个应用程序问题,但JVM超过了堆的3GB最大设置。 使用top我看到:

  PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 8449 apache 18 0 19.6g 6.9g 5648 S 4.0 84.8 80:42.27 java 

那么具有3GB堆,256MB permgen甚至一些开销的JVM怎么能消耗6.9GB? JVM中的错误可以通过升级到构建#35来修复吗? 在java中可能使用额外内存的东西缺少什么? 试着看看有没有人见过这个。

那么具有3GB堆,256MB permgen甚至一些开销的JVM怎么能消耗6.9GB?

可能的解释包括:

  • 很多很multithreading堆栈,
  • 内存映射文件应该在它们应该关闭时,
  • 一些使用(可能泄漏)堆外内存的本机代码库。

在责备JVM之前,我倾向于责怪应用程序。

长话短说,我最初的反应是正确的,这是JVM中的一个错误。 我们使用的是1.6.0_21,结果发现我们遇到了与https://confluence.atlassian.com/pages/viewpage.action?pageId=219023686中概述的完全相同的错误。 升级到1.6.0_37修复了问题,我们从每日崩溃到2周而没有崩溃。

因此,虽然不仅仅归咎于JVM的情绪是一个好的策略,但似乎还应该建议不要总是假设JVM没有bug,就像所有软件偶尔会有bug一样。 另外,似乎是保持最新状态的好政策。

感谢您对此的所有帮助!

http://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/geninfo/diagnos/garbage_collect.html

请注意,JVM使用的内存多于堆。 例如,Java方法,线程堆栈和本机句柄分配在与堆不同的内存中,以及JVM内部数据结构中。

因此,如果您拥有大量线程和大量本机句柄,则内存可能会超出堆限制。 你确定之前没发生这种情况吗?

另请查看: Java使用的内存多于分配的内存