Java虚拟内存大小大于请求(或必需)

时间:2015-05-13 09:42:01

标签: java memory

我正在计算群集上运行多个作业,当它们超过请求的资源使用时会被杀死 - 其中一个用途是虚拟内存大小。

在我的java启动命令中,我使用-Xmx8000m来表示初始堆栈大小为8GB,我还没有看到我的程序的实际内存使用量超过4GB,但是为了安全起见。

但是,当我使用top命令时,我看到我的java进程的虚拟内存大小为12GB - 正好在所请求的虚拟内存空间的限制。由于作业已经提交,我无法增加我所请求的VM大小,而且我要求他们花费的时间越长。

Java是否一致地请求比指定的VM堆空间更多?这是一个恒定的数量,或恒定的%或随机?堆空间是否可以增长到a)请求的VM大小(8GB)或b)分配的VM大小(12GB)。

编辑: 在Linux上使用jre-1.7.0-openjdk

3 个答案:

答案 0 :(得分:7)

本文对该问题进行了很好的分析:Why does my Java process consume more memory than Xmx其作者提供了这个近似公式:

Max memory = [-Xmx] + [-XX:MaxPermSize] + number_of_threads * [-Xss]
  

但除了应用程序消耗的内存之外,还有JVM本身   还需要一些肘部空间。   - 垃圾收集。    - JIT优化。    - 堆外分配。    - JNI代码。    - Metaspace。

但要小心,因为它可能取决于平台和JVM供应商/版本。

答案 1 :(得分:4)

这可能是由于glibc 2.10+中malloc行为的变化,malloc现在创建了每线程内存池(竞技场)。 64位的竞技场大小为64MB。在64位上使用8个竞技场之后,malloc将竞技场的数量设置为number_of_cpus * 8.因此,如果您使用的是具有多个处理器核心的计算机,则即使实际内存,虚拟大小也会非常快速地设置使用(居民大小)要小得多。

由于您看到顶级显示12GB虚拟大小,您可能正在使用具有24个内核或硬件线程的64位计算机,提供24 * 8 * 64MB = 12GB。分配的虚拟内存量因内核数量而异,并且数量将根据您的作业发送到的计算机上的内核数量而变化,因此此检查没有意义。

如果您使用hadoop或yarn并获取,请将yarn-site.xml中的yarn.nodemanager.vmem-check-enabled设置为false

参考文献:

请参阅本页第6页:

http://blog.cloudera.com/blog/2014/04/apache-hadoop-yarn-avoiding-6-time-consuming-gotchas/

链接到此页面上的更深入讨论:

https://www.ibm.com/developerworks/community/blogs/kevgrig/entry/linux_glibc_2_10_rhel_6_malloc_may_show_excessive_virtual_memory_usage

请注意,此stackoverflow页面已经部分回答:

Container is running beyond memory limits

答案 2 :(得分:0)

您真的很想调查此问题并且您在Linux上然后检查您的jvm进程的PID并查看文件/proc/<PID>/smaps。在那里,您将找到整个操作系统进程内存映射 - 如内核所示。您将看到mach堆(OS堆)进程如何使用,哪些内存区域从文件(库)映射,等等。

PS:你也可以在互联网上提交各种工具来分析smaps文件。