Java JVM 崩溃,错误=“无法分配内存”(errno=12)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46801741/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 02:28:55  来源:igfitidea点击:

JVM crashes with error='Cannot allocate memory' (errno=12)

javamemory-management

提问by Generic Person

My code crashes with this error message

我的代码因此错误消息而崩溃

Executing "/usr/bin/java  com.utils.BotFilter"
OpenJDK 64-Bit Server VM warning: INFO: 
os::commit_memory(0x0000000357c80000, 2712666112, 0) failed; 
error='Cannot allocate memory' (errno=12)

There is insufficient memory for the Java Runtime Environment to continue. Native memory allocation (malloc) failed to allocate 2712666112 bytes for committing reserved memory. An error report file with more information is saved as: /tmp/jvm-29955/hs_error.log`

没有足够的内存供 Java 运行时环境继续使用。本机内存分配 (malloc) 未能为提交保留内存分配 2712666112 字节。包含更多信息的错误报告文件保存为:/tmp/jvm-29955/hs_error.log`

Here is the content of the generated hs_error.log file:

这是生成的内容hs_error.log file

https://pastebin.com/yqF2Yy4P

https://pastebin.com/yqF2Yy4P

This line from crash log seems interesting to me:

崩溃日志中的这一行对我来说似乎很有趣:

Memory: 4k page, physical 98823196k(691424k free), swap 1048572k(0k free)

Does it mean that the machine has memory but is running out of swap space?

这是否意味着机器有内存但交换空间不足?

Here is meminfo from the crash log but I don't really know how to interpret it, like what is the difference between MemFree and MemAvailable? How much memory is this process taking?

这是崩溃日志中的 meminfo,但我真的不知道如何解释它,比如 MemFree 和 MemAvailable 之间有什么区别?这个过程占用了多少内存?

/proc/meminfo:

/proc/meminfo

MemTotal:       98823196 kB
MemFree:          691424 kB
MemAvailable:    2204348 kB
Buffers:          145568 kB
Cached:          2799624 kB
SwapCached:       304368 kB
Active:         81524540 kB
Inactive:       14120408 kB
Active(anon):   80936988 kB
Inactive(anon): 13139448 kB
Active(file):     587552 kB
Inactive(file):   980960 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:       1048572 kB
SwapFree:              0 kB
Dirty:              1332 kB
Writeback:             0 kB
AnonPages:      92395828 kB
Mapped:           120980 kB
Shmem:           1376052 kB
Slab:             594476 kB
SReclaimable:     282296 kB
SUnreclaim:       312180 kB
KernelStack:      317648 kB
PageTables:       238412 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:    50460168 kB
Committed_AS:   114163748 kB
VmallocTotal:   34359738367 kB
VmallocUsed:      314408 kB
VmallocChunk:   34308158464 kB
HardwareCorrupted:     0 kB
AnonHugePages:  50071552 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:      116924 kB
DirectMap2M:     5115904 kB
DirectMap1G:    95420416 kB

回答by Scary Wombat

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=
  • In case you have many contexts wars deployed on your tomcat try reduce them
  • 减少系统内存负载
  • 增加物理内存或交换空间
  • 检查交换后备存储是否已满
  • 在 64 位操作系统上使用 64 位 Java
  • 减少 Java 堆大小 (-Xmx/-Xms)
  • 减少 Java 线程数
  • 减少 Java 线程堆栈大小 (-Xss)
  • 使用 -XX:ReservedCodeCacheSize= 设置更大的代码缓存
  • 如果您在 tomcat 上部署了许多上下文战争,请尝试减少它们

回答by Patricio Carranza

As Scary Wombatmentions, the JVM is trying to allocate 2712666112 bytes (2.7 Gb) of memory, and you only have 691424000 bytes (0.69 Gb) of free physical memory and nothing available on the swap.

正如Scary Wombat 所提到的,JVM 试图分配 2712666112 字节(2.7 Gb)的内存,而您只有 691424000 字节(0.69 Gb)的空闲物理内存,交换中没有任何可用空间。

回答by creinig

Another possibility (which I encountered just now) would be bad settings for "overcommit memory" on linux.

另一种可能性(我刚才遇到的)是 linux 上“过量使用内存”的错误设置。

In my situation, /proc/sys/vm/overcommit_memorywas set to "2" and /proc/sys/vm/overcommit_ratioto "50" , meaning "don't ever overcommit and only allow allocation of 50% of the available RAM+Swap".

在我的情况下,/proc/sys/vm/overcommit_memory设置为 "2" 和/proc/sys/vm/overcommit_ratio"50" ,意思是“永远不要过度使用,只允许分配 50% 的可用 RAM+Swap”。

That's a pretty deceptive problem, since there can be a lot of memory available, but allocations still fail for apparently no reason.

这是一个相当具有欺骗性的问题,因为可能有大量可用内存,但分配仍然毫无理由地失败。

The settings can be changed to the default (overcommit in a sensible way) for now (until a restart):

现在(直到重新启动)可以将设置更改为默认值(以合理的方式过度使用):

echo 0 >/proc/sys/vm/overcommit_memory

... or permanently:

...或永久:

echo "vm.overcommit_memory=0 >> /etc/sysctl.conf
sysctl -p /etc/sysctl.conf # apply it immediately

Note: this can also partly be diagnosed by looking at the output of /proc/meminfo:

注意:这也可以通过查看以下输出来部分诊断/proc/meminfo

...
CommitLimit:    45329388 kB
Committed_AS:   44818080 kB 
...

In the example in the question, Committed_ASis much higher than CommitLimit, indicating (together with the fact that allocations fail) that overcommit is enabled, while here both values are close together, meaning that the limit is strictly enforced.

在问题的示例中,Committed_AS远高于CommitLimit,表明(连同分配失败的事实)启用了过量使用,而此处两个值接近在一起,这意味着严格执行限制。

An excellent detailed explanation of these settings and their effect (as well as when it makes sense to modify them) can be found in this pivotal blog entry. (Tl;dr: messing with overcommit is useful if you don't want critical processes to use swap)

在这个关键的博客条目中可以找到对这些设置及其效果(以及何时修改它们有意义)的出色详细说明。(Tl; dr:如果您不希望关键进程使用交换,那么处理过度使用会很有用)