Tomcat扔掉了一句话;java.lang.OutOfMemoryError:java堆空间“;,但转储中的堆大小小于-Xmx

Tomcat扔掉了一句话;java.lang.OutOfMemoryError:java堆空间“;,但转储中的堆大小小于-Xmx,java,jvm,out-of-memory,Java,Jvm,Out Of Memory,我们的tomcat服务器抛出了“java.lang.OutOfMemoryError:java堆空间”,但转储文件中的堆大小只有1.7GB,-Xmx是4GB 我不知道发生了什么事,你能帮我吗 环境: Redhat tomcat6 jdk6首先您需要查看以下内存参数,它可能无法阻止OutOfMemoryError,但您应该了解它们: -Xmx2048m -> this param to set the max memory that the JVM can allocate -Xms1024

我们的tomcat服务器抛出了“java.lang.OutOfMemoryError:java堆空间”,但转储文件中的堆大小只有1.7GB,-Xmx是4GB

我不知道发生了什么事,你能帮我吗

环境:
Redhat tomcat6 jdk6

首先您需要查看以下内存参数,它可能无法阻止
OutOfMemoryError
,但您应该了解它们:

-Xmx2048m -> this param to set the max memory that the JVM can allocate
-Xms1024m -> the init memory that JVM will allocate on the start up
-XX:MaxPermSize=512M -> this for the max Permanent Generation memory
此外,您可能还需要检查这些参数,这些参数将加快年轻空间上的
GC
活动,因此收集效果会更好

-XX:MaxNewSize=  -> this need to be 40% from your Xmx value
-XX:NewSize=614m -> this need to be 40% from your Xmx value
您还可以告诉您使用什么类型的
JVM
(我认为最新的
JVM
版本中已经启用了这种类型):

当发生
OutOfMemoryError
时,
JVM
将触发
Stop World GC
,因此它将收集您的对象和未引用的对象,这就是堆大小小于您的
-Xmx
值的原因


通常,在这种情况下,如果使用一个分析工具来分析这个堆,你会清楚地发现那些填充了你的内存的大对象,这些代码会引导你进入代码,并且很容易修复它。

< P > Salh的回答是错误的,在这么多的层次上,我会认为这是完全有害的。p> 首先,JVM不会在OutOfMemoryError死掉之前触发停止World GC并清除堆。OOM的原因是GC无法清理内存,通常是在OOM之前的数十次和数百次运行中


其次,JVM供应商实际上并不推荐推荐推荐的比率。最佳比率严重依赖于应用程序,因此在不知道您在做什么的情况下,最好保留默认值,而不是遵循此建议。

XmxSIZE
可能比Java核心转储更大,因为
OutOfMemory
发生在您尝试分配大型对象时

我们的应用程序带有
-Xmx1000m
和670 MiB转储,在用户上载300 MiB附件时被
OutOfMemory
崩溃

我们在
System.arrayCopy
上的“显示线程”跟踪中的VisualVM中发现了这一点。从本地堆栈帧变量点到300 MiB字节数组的引用


现在,我们限制附件大小并避免应用程序将来崩溃。

为什么NewSize应该是40%,你能提供一些参考文档吗?不应该,建议检查一下。如果JVM可以用STW GC清理这么多内存,那么为什么要抛出OOM?Salah,Oracle到底在哪里建议40%的总堆是新的?@Nikem,你的第一个问题与OP真正要问的完全不同,他问为什么会在
OutOfMemoryError
发生时生成堆,因为通常在写入堆转储之前会触发一个完整的GC,因此它包含关于剩余对象的信息。是的,我不明白为什么jvm抛出OOM,而GC可以将堆清理到1.7GB。
-XX:+UseConcMarkSweepGC