Java虚拟内存大小大于请求的(或需要的)大小
Java虚拟内存大小大于请求的(或需要的)大小
我在计算集群上运行了一些作业,当它们超过所请求的资源使用时,它们就会被终止,其中一个使用的是虚拟内存大小。
在我的Java启动命令中,我使用-Xmx8000m
来表示初始堆栈大小为8GB,我还没有看到我的程序实际的内存使用量超过4GB,但想要更加安全。
然而,当我使用top命令时,我看到我的Java进程的虚拟内存大小为12GB - 正好达到所请求的虚拟内存空间的极限。我不能增加所请求的VM大小,因为作业已经提交,而且我提出的要求越多,它们被安排的时间就越长。
Java是否始终请求比指定的VM堆空间更多的空间?这是一个固定的量,还是一个固定的百分比或者随机的?堆空间是否会超过a)请求的VM大小(8GB)或b)分配的VM大小(12GB)?
编辑:
在Linux上使用jre-1.7.0-openjdk
这可能是由于glibc 2.10+中malloc行为的更改导致的,其中malloc现在创建每个线程的内存池(arena)。64位系统上的arena大小为64MB。在64位系统上使用8个arena后,malloc将arena数设置为number_of_cpus * 8。因此,如果您使用的是拥有许多处理器核心的机器,则虚拟大小会非常快地设置为大量,即使实际使用的内存(常驻大小)要小得多。
由于您在top中看到12GB虚拟大小,所以您可能正在使用具有24个核心或硬件线程的64位机器,即24 * 8 * 64MB = 12GB。分配的虚拟内存量随核心数而变化,该量将根据您的作业在其上运行的机器上的核心数而更改,因此这种检查没有意义。
如果您正在使用hadoop或yarn并收到警告,请在yarn-site.xml中将yarn.nodemanager.vmem-check-enabled
设置为false
。
参考文献:
请参考本页面上的#6:
https://blog.cloudera.com/blog/2014/04/apache-hadoop-yarn-avoiding-6-time-consuming-gotchas/
该页面链接到了更深入的讨论页面:
注意这已经部分地在这个stackoverflow页面上回答了:
这篇文章对问题进行了很好的分析:为什么我的Java进程比Xmx指定的内存更多?作者提供了以下近似公式:
Max memory = [-Xmx] + [-XX:MaxPermSize] + number_of_threads * [-Xss]
除了应用程序消耗的内存外,JVM本身也需要一些余地。
- 垃圾回收。
- JIT优化。
- Off-heap分配。
- JNI代码。
- 元空间。
但要注意这可能取决于平台和JVM供应商/版本。