JVM内存崩溃不足

时间:2018-03-16 09:50:14

标签: java jvm

我一直在使用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)

2 个答案:

答案 0 :(得分:0)

  

将-Xms和-Xmx设置为相同的值可以帮助我们

这是一个好主意。在最坏的情况下,它会在JVM启动后立即崩溃,这意味着Xmx比系统中的可用内存大。您还应该监控主机内存和交换使用,而不仅仅是JVM在运行时报告的内容。*内存。还要检查操作系统是否以某种方式限制应用程序可用的内存,例如linux中的overcommit内核设置。

答案 1 :(得分:0)

  

将-Xms和-Xmx设置为相同的值可以帮助我们

可能不是。您的JVM堆空间不是问题,但需要注意的是,如果您允许的堆空间超过操作系统可以提供的空间,那么您将遇到问题。

错误消息的关键部分是:

  

本机内存分配(malloc)无法为ChunkPool :: allocate

分配32744个字节
当操作系统无法将内存分配给JVM进程时,

malloc()将失败。要检查的事项:

  1. 在您的应用运行时监控并记录整体机器内存使用情况,包括交换。

  2. 使用ulimit -m检查用户的流程大小是否存在管理员限制。共享服务器通常有限制来阻止一个用户占用所有资源。

  3. 如果在容器中运行,则上述两者都适用,但您还需要检查容器管理技术(例如Kubernetes)施加的资源限制。