jvm出现Cannot allocate memory问题解决

Scroll Down

问题现象

今天安装Elasticsearch 5.6.3,在启动ES后台服务时,日志显示JVM报出Cannot allocate memory错误。
JDK版本:jdk-8u261-linux-x64

问题分析

内存不足?
网上查询,大多都是说内存不足或swap空间不足,所以jvm无法申请内存。

free -h查看内存,发现空闲内存还有3.7G,申请的内存只有600多M,肯定不是内存不足的问题。另外虚机没有配置swap空间,swap为0。有文章说jvm会根据swap剩余空间,来决定内存是否能申请成功。这倒有可能是一个因素,但应该不是主要原因,继续找答案。。。

JDK问题?
中间想到过是不是JDK问题,但想想可能性极小,放在最后考虑,先继续找答案。。。

然后,找到了这么一篇文章:Cannot allocate memory 的分析及解决方法

成功解决了问题!

以下会介绍解决问题的过程,并附上分析,可以直接往下看,无需看原文。当然,对某些问题之外的细节感兴趣的,可以看看原文,讲的比较细致。

解决过程

1.像上面所说既然是内存申请失败,首先查看内存是否不足。

free -h

发现空闲内存有3.7G,排除问题。

2.查看是否为进程过多
查看服务器最大进程数,数量3w+

sysctl kernel.pid_max

查看当前进程数,数量为几百,排除问题。

ps -eLf | wc -l

3.查看磁盘是否写满
磁盘也没满,排除问题

df -h

4.查看linux内核参数overcommit_memory

Linux下有个内核参数overcommit_memory,是内存分配策略,程序在启动的时候会先去申请内存,尽管不一定都会用的到那么多。此参数决定是否接受超大内存请求的条件。这个参数有三个可能的值:

0:默认设置。内核执行启发式内存过量使用处理,方法是估算可用内存量,并拒绝明显无效的请求。遗憾的是因为内存是使用启发式而非准确算法计算进行部署,这个设置有时可能会造成系统中的可用内存超载。

1:内核执行无内存过量使用处理。使用这个设置会增大内存超载的可能性,但也可以增强大量使用内存任务的性能。

2:内存拒绝等于或者大于总可用 swap 大小以及overcommit_ratio指定的物理RAM比例的内存请求。如果您希望减小内存过度使用的风险,这个设置就是最好的。

cat /proc/sys/vm/overcommit_memory

发现值为2!

查看可申请内存总量和已提交内存数,发现剩余很少。

cat /proc/meminfo | grep Commit

这应该是问题所在了!

解决问题:
接下来,修改overcommit_memory的值

vim /etc/sysctl.conf 

发现文件中该参数的值为2,把它修改为2

vm.overcommit_memory=1

使配置生效

sysctl -p

再启动ES后台,成功启动,问题解决!