我一直在使用G1垃圾收集器遇到Java VM崩溃。我们获得了使用以下签名生成的hs_err_pid.log文件:
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (malloc) failed to allocate 32744 bytes for ChunkPool::allocate
# Possible reasons:
# The system is out of physical RAM or swap space
# In 32 bit mode, the process size limit was hit
# Possible solutions:
# Reduce memory load on the system
# Increase physical memory or swap space
# Check if swap backing store is full
# Use 64 bit Java on a 64 bit OS
# Decrease Java heap size (-Xmx/-Xms)
# Decrease number of Java threads
# Decrease Java thread stack sizes (-Xss)
# Set larger code cache with -XX:ReservedCodeCacheSize=
# This output file may be truncated or incomplete.
我们目前正在使用Runtime.maxMemory,freeMemory和totalMemory监视内存可用性并抢占任何内存不足错误。我们的想法是,我们可以暂停操作并警告用户他们需要分配更多内存。但是,即使Runtime.freeMemory报告了大量可用内存,我们也看到上述JVM崩溃。
作为一个Java桌面应用程序,我们可以避免这种情况发生,并使自己与系统上的内存负载隔离开来。 例如,我们可以提供任何启动选项的组合,即将-Xms和-Xmx设置为相同的值可以帮助我们吗?目前我们只设置-Xmx。
我热衷于避免Jvm静默崩溃的糟糕用户体验。理想情况下,我们希望能够检测到JVM何时接近内存并采取适当的措施。
以下是针对一个示例崩溃从hs_err_pid.log获取的更多信息。这是使用-Xmx4g,总物理内存12gb,可用物理内存1.79gb。
Native memory allocation (malloc) failed to allocate 32744 bytes for ChunkPool::allocate
Heap:
garbage-first heap total 4194304K, used 3140260K [0x00000006c0000000, 0x00000006c0108000, 0x00000007c0000000)
region size 1024K, 1526 young (1562624K), 26 survivors (26624K)
Metaspace used 78244K, capacity 95308K, committed 96328K, reserved 1122304K
class space used 11319K, capacity 22311K, committed 23112K, reserved 1048576K
Memory: 4k page, physical 12269248k(1790928k free), swap 37973052k(362096k free)
答案 0 :(得分:0)
将-Xms和-Xmx设置为相同的值可以帮助我们
这是一个好主意。在最坏的情况下,它会在JVM启动后立即崩溃,这意味着Xmx比系统中的可用内存大。您还应该监控主机内存和交换使用,而不仅仅是JVM在运行时报告的内容。*内存。还要检查操作系统是否以某种方式限制应用程序可用的内存,例如linux中的overcommit
内核设置。
答案 1 :(得分:0)
将-Xms和-Xmx设置为相同的值可以帮助我们
可能不是。您的JVM堆空间不是问题,但需要注意的是,如果您允许的堆空间超过操作系统可以提供的空间,那么您将遇到问题。
错误消息的关键部分是:
当操作系统无法将内存分配给JVM进程时,本机内存分配(malloc)无法为ChunkPool :: allocate
分配32744个字节
malloc()
将失败。要检查的事项:
在您的应用运行时监控并记录整体机器内存使用情况,包括交换。
使用ulimit -m
检查用户的流程大小是否存在管理员限制。共享服务器通常有限制来阻止一个用户占用所有资源。
如果在容器中运行,则上述两者都适用,但您还需要检查容器管理技术(例如Kubernetes)施加的资源限制。