18

我们有一个从 Java 1.5.0.19 升级到 Java 1.6.0.21 的 Java webapp

/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 最大设置。使用顶部我看到:

 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 中的错误将通过升级到 build #35 来修复?java中缺少的东西可能会使用额外的内存?只是想看看有没有人以前见过这个。

4

3 回答 3

14

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

可能的解释包括:

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

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

于 2012-09-06T03:11:39.090 回答
12

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

因此,虽然不只是责备 JVM 是一个好政策,但似乎也应该建议人们不要总是假设 JVM 没有错误,就像所有软件都有偶尔的错误一样。另外,保持最新状态似乎是个好政策。

感谢您对此的所有帮助!

于 2012-11-08T21:29:46.027 回答
2

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

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

所以如果你有很多线程和很多本机句柄,内存可能会超过堆限制。你确定这也没有发生过吗?

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

于 2012-09-06T03:03:43.923 回答