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

时间:2012-09-06 02:57:42

标签: java memory-management memory-leaks

我们有一个Java webapp,我们从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中的内容可能会使用额外的内存?试着看看有没有人见过这个。

3 个答案:

答案 0 :(得分:12)

  

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

可能的解释包括:

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

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

答案 1 :(得分:9)

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

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

感谢您对此提供的所有帮助!

答案 2 :(得分:2)

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

  

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

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

另请查看:Java using more memory than the allocated memory