一、Linux内核OOM killer机制
Linux 内核有个机制叫OOM killer(Out Of Memory killer),该机制会监控那些占用内存过大,尤其是瞬间占用内存很快的进程,然后防止内存耗尽而自动把该进程杀掉。内核检测到系统内存不足、挑选并杀掉某个进程的过程可以参考内核源代码linux/mm/oom_kill.c,当系统内存不足的时候,out_of_memory()被触发,然后调用select_bad_process()选择一个”bad”进程杀掉。如何判断和选择一个”bad进程呢?linux选择”bad”进程是通过调用oom_badness(),挑选的算法和想法都很简单很朴实:最bad的那个进程就是那个最占用内存的进程。
被干掉进程信息
如需输出确认了被kill的进程为17982
[511250.459581] Out of memory: Kill process 17982 (java) score 77 or sacrifice child
[511250.459642] Killed process 17982 (java) total-vm:19803312kB, anon-rss:2540308kB, file-rss:0kB, shmem-rss:0kB
如下为17982进程占用的内存页数量635077,换算为内存占用量是635077*4096=2GB
[511250.459172] [ pid ] uid tgid total_vm rss nr_ptes swapents oom_score_adj name
[511250.459549] [17982] 996 17982 4950828 635077 1629 0
每列的含义为:
-
pid进程ID。
-
uid用户ID。
-
tgid线程组ID。
-
total_vm虚拟内存使用(单位为4 kB内存页)
-
rss居民 memory 使用(单位4 kB内存页)
-
nr_ptes页表项
-
swapents交换条目
-
oom_score_adj通常为0;较低的数字表示当调用OOM杀手时,进程将不太可能死亡。
二、解决方法
1、调整JVM 最大内存,小于系统最大物理内存。
2、开启swap内存交换,参考:https://www.cnblogs.com/cheyunhua/p/8653168.html
3、关闭oomkiller。
当然,如果需要的话可以完全关闭 OOM killer(不推荐用在生产环境):
# sysctl -w vm.overcommit_memory=2 # echo "vm.overcommit_memory=2" >>
参考文献: