Tomcat抛出“java.lang.OutOfMemoryError:Java堆空间”,但转储中的堆大小小于-Xmx

问题描述 投票:5回答:3

我们的tomcat服务器抛弃了“java.lang.OutOfMemoryError:Java堆空间”,但转储文件中的堆大小仅为1.7GB,-Xmx为4GB。

我不确定发生了什么事,你能帮助我吗?

环境:Redhat tomcat6 jdk6

java jvm out-of-memory
3个回答
2
投票

XmxSIZE可能比Java核心转储更大,因为当你尝试分配一个大对象时会发生OutOfMemory

我们使用-Xmx1000m和670 MiB转储的应用由OutOfMemory在用户上传300 MiB附件时崩溃。

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

现在我们限制附件大小并将我们的应用程序从未来崩溃中保存下来。


1
投票

萨拉赫的回答在很多层面都是错误的,我认为这是完全有害的。

首先,在使用OutOfMemoryError死之前,JVM不会触发Stop The World GC并清除堆。 OOM的原因是GC无法清理内存,通常是在OOM之前的数十次和数百次运行期间。

其次,JVM供应商实际上并不推荐建议的比率。最佳比率在很大程度上取决于应用程序,所以不知道你在做什么,最好保留默认值而不是遵循这个建议。


0
投票

首先,您需要查看以下内存参数,它可能无法阻止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

此外,您可能还想检查这些参数,这些参数将加速您的Young空间上的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使用什么类型的GC(我认为这种类型已经在最新的JVM版本中启用):

-XX:+UseConcMarkSweepGC

第二

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

通常在这种情况下,如果您使用其中一个分析工具分析了这个堆,您将清楚地找到填充内存的大对象,这将导致您获得代码,并且很容易修复它。

© www.soinside.com 2019 - 2024. All rights reserved.