繁体   English   中英

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

[英]Java virtual memory size larger than requested (or required)

我在计算集群上运行了许多作业,当它们超过请求的资源使用情况时,它们就会被终止——其中一种用途是虚拟内存大小。

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

但是,当我使用 top 命令时,我看到我的 java 进程的虚拟内存大小为 12GB - 这正好是请求的虚拟内存空间的限制。 我无法增加我请求的 VM 大小,因为作业已经提交,而且我要求的越多,它们被安排的时间就越长。

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

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

这篇文章很好的分析了这个问题: 为什么我的Java进程比Xmx消耗更多的内存,并且它的作者提供了这个近似公式:

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

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

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

这可能是由于 glibc 2.10+ 中 malloc 行为的变化,其中 malloc 现在创建每线程内存池(arenas)。 64 位的 Arena 大小为 64MB。 在 64 位上使用 8 个 arenas 后,malloc 将 arenas 的数量设置为 number_of_cpus * 8。因此,如果您使用具有许多处理器内核的机器,则虚拟大小会很快设置为大量,即使实际内存使用(居民大小)要小得多。

由于您看到 top 显示 12GB 虚拟大小,您可能正在使用具有 24 个内核或 HW 线程的 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-sumption-gotchas/

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

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

请注意,在此 stackoverflow 页面上已经部分回答了这一点:

容器运行超出内存限制

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM