我们的Tomcat服务器抛出了“java.lang.OutOfMemoryError: Java heap space”错误,但转储文件中的堆大小仅为1.7GB,而-Xmx为4GB。
我不确定发生了什么,请你帮助我解决这个问题。
环境:
Redhat tomcat6 jdk6
XmxSIZE
可以比Java核心转储更大,因为在尝试分配大型对象时会发生OutOfMemory
!我们的应用程序使用-Xmx1000m
和670 MiB转储,在用户上传300 MiB附件时由于OutOfMemory
而崩溃。我们在“显示线程”跟踪中的VisualVM中发现了这一点,其中System.arrayCopy
被调用。来自本地堆栈帧变量的引用指向300 MiB字节数组。现在我们限制附件大小并保护我们的应用程序免受未来崩溃的影响。Salah的回答在很多方面都是错误的,我认为这是直接有害的。
首先,JVM不会在死亡之前触发Stop The World GC并清理堆内存以避免OutOfMemoryError。造成OOM的原因是GC未能在OOM之前清理内存,通常是在数十次和数百次运行期间。
其次,推荐的比率实际上并非JVM供应商推荐的。最佳比率严重依赖于应用程序,因此如果不知道您在做什么,最好保持默认设置而不是遵循此建议。
首先,您需要查看以下内存参数,这可能无法防止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
值。
通常在这种情况下,如果您使用其中一种分析工具分析此堆,则会清楚地找到填充内存的大型对象,这将使您进入代码并很容易修复它。
30%
,因此几乎为640k
。 - Salah