JVM 超过 -Xmx 定义的最大内存

2022-09-02 21:02:35

我们有一个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。使用顶部我看到:

 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中缺少一些东西可以使用额外的内存?只是想看看以前是否有人见过这个。


答案 1

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

可能的解释包括:

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

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


答案 2

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

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

感谢您对此的所有帮助!


推荐