繁体   English   中英

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

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

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

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)

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

以下是生成的hs_error.log file的内容:

https://pastebin.com/yqF2Yy4P

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

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

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

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

/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

可能的解决方案:

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

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

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

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

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

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

echo 0 >/proc/sys/vm/overcommit_memory

...或永久:

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

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

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

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

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

暂无
暂无

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

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