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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12292368/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 08:19:48  来源:igfitidea点击:

JVM exceeds maximum memory defined with -Xmx

javamemory-managementmemory-leaks

提问by Benny the Guard

We have a Java webapp that we upgraded from Java 1.5.0.19 to Java 1.6.0.21

我们有一个从 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

As you can see it should preallocate 2GB of heap and max out at 3GB (why we preallocate so much is because this app is ancient and poorly designed so has a ton of things to load up). The issue we have seen recently after upgrading to the 1.6 is that on occasion memory goes through the roof. While memory usage is likely an app issue the JVM is exceeding the 3GB max setup for heap. Using top I see:

正如您所看到的,它应该预分配 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             

So how could a JVM with 3GB heap, 256MB permgen, and even some overhead consume 6.9GB? Bug in the JVM that would be fixed by upgrading to build #35? Something missing on what in java could be using the extra memory? Just trying to see if anyone has seen this before.

那么具有 3GB 堆、256MB permgen 甚至一些开销的 JVM 怎么会消耗 6.9GB 呢?JVM 中的错误将通过升级到 build #35 来修复?java中缺少什么可能会使用额外的内存?只是想看看是否有人以前见过这个。

回答by Stephen C

So how could a JVM with 3GB heap, 256MB permgen, and even some overhead consume 6.9GB?

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

Possible explanations include:

可能的解释包括:

  • lots and lots of thread stacks,
  • memory-mapped files that are not being closed when they should be,
  • some native code library using (possibly leaking) out-of-heap memory.
  • 大量的线程堆栈,
  • 应该关闭但没有关闭的内存映射文件,
  • 一些使用(可能泄漏)堆外内存的本机代码库。

I would be inclined to blame the application before blaming the JVM.

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

回答by Benny the Guard

So long story short, my initial reaction was correct it was a bug in the JVM. We were using 1.6.0_21 and it turns out that we were experiencing the exact same error as outlined in https://confluence.atlassian.com/pages/viewpage.action?pageId=219023686. Upgrading to 1.6.0_37 fixed the problem and we went from daily crashes to 2 weeks without a crash.

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

So while the sentiment to not just blame the JVM is a good policy it seems that one should also be advised not to always assume the JVM is bug free, it like all software has the occasional bug. Plus, seems good policy to keep things up to date.

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

Thanks for all the help on this one!

感谢您对此的所有帮助!

回答by Peter Ilfrich

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

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

Note that the JVM uses more memory than just the heap. For example Java methods, thread stacks and native handles are allocated in memory separate from the heap, as well as JVM internal data structures.

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

So if you have a lot of threads and a lot of native handles, the memory can exceed the heap limit. Are you sure this didn't happen before as well?

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

Also check out this: Java using more memory than the allocated memory

另请查看:Java using more memory than the分配的内存