1、查找进程
通过jps -l查找相关的进程发现进程已经不存在
2、查看服务日志
查看服务日志后,发现凌晨4点53并未产生相关的错误日志导致程序出现OOM,此时进行进一步分析,是否是linux杀掉了进程
3、查看linux系统日志
通过less /var/logs/message查询到有相关的java进程被杀掉的日志记录,因为当时java进程是按照的7g堆内存进行启动的。
java -jar -Xms7000m -Xmx7000m -Dspring.profiles.active=test
而linux根据系统评分把当前java进程占用内存高评分为313,所以linux内核为了自保而把当前java进程给杀掉了,而具体是因为什么原因造成的呢?
4、查看机器的内存占用
发现当时启动7G内存确实可以把服务正常启动
5、实际分析
Linux内核根据应用程序的要求分配内存,通常来说应用程序分配了内存但是并没有实际全部使用,为了提高性能,这部分没用的内存可以留作它用,这部分内存是属于每个进程的,内核直接回收利用的话比较麻烦,所以内核采用一种过度分配内存(over-commit memory)的办法来间接利用这部分“空闲”的内存,提高整体内存的使用效率。一般来说这样做没有问题,但当大多数应用程序都消耗完自己的内存的时候麻烦就来了,因为这些应用程序的内存需求加起来超出了物理内存(包括swap)的容量,内核(OOM killer)必须杀掉一些进程才能腾出空间保障系统正常运行。
Linux内核有个机制叫OOM killer(Out-Of-Memory killer),该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了防止内存耗尽内核会把该进程杀掉。 从上面的 oom_kill.c 代码里可以看到 oom_badness() 给每个进程打分,根据 points 的高低来决定杀哪个进程,这个 points 可以根据 adj 调节,root 权限的进程通常被认为很重要,不应该被轻易杀掉,所以打分的时候可以得到 3% 的优惠(分数越低越不容易被杀掉)。
6、总结
通俗的话来说,其实因为java进程占用内存太高,被linux进程评为最高分,linux内核为了自保,而把评分高的进程给杀死,如果这个java进程设置不可杀死,可能会造成linux死机,而实际查到linux上当时还有其余的一些服务在运行,其余的服务在申请内存的时候,发现内存不够,但是linux为自保就把评分高的进程给杀掉了。
原因:
当时还有一个docker启动的一些服务,停掉后会自动拉起,而造成原因是这些服务申请内存的时候造成了linux杀掉了评分高的服务