记录一次java应用突然挂掉的问题定位

2023-03-31 09:50:24 浏览数 (1)

问题背景:一次启动本地应用,两分钟过后自动退出,通过日志并未发现任何异常状况,莫名其妙的应用就自动被杀掉了;

1、linux通过top查看java应用内存和cpu都不高,只是过一会突然就没了;

2、通过应用日志并未查到有任何异样,代码也走查了好几遍;

3、通过dmesg | grep java查看内核日志信息,发现了问题所在,如下:

代码语言:javascript复制
[16949523.941194] java invoked oom-killer: gfp_mask=0xd0, order=0, oom_score_adj=991
[16949523.942914] java cpuset=73a35980233979bb67f20700c76d77805de6ced7cfd18de836238a7bdae7c1dd mems_allowed=0
[16949523.942918] CPU: 4 PID: 310033 Comm: java Tainted: G     U     O 3.10.107-1-tlinux2_kvm_guest-0052 #1
[16949523.971234] Memory cgroup out of memory: Kill process 310033 (java) score 1964 or sacrifice child
[16949523.973103] Killed process 182650 (java) total-vm:16705124kB, anon-rss:2079844kB, file-rss:22020kB

以上信息可以看到内存溢出被linux杀掉的java应用信息;

4、但是我应用内存占用并不是特别高,通过jinfo -flags <javapid>发现java应用的启动预申请内存达到了10G;

5、通过free或者vmstat查看剩余内存大小只有10G了,内核检测到系统内存不足、挑选并杀掉某个进程的过程可以参考内核源代码 linux/mm/oom_kill.c,当系统内存不足的时候,out_of_memory() 被触发,然后调用 select_bad_process() 选择一个 “bad” 进程杀掉,如何判断和选择一个 “bad” 进程呢,总不能随机选吧?挑选的过程由 oom_badness() 决定,挑选的算法和想法都很简单很朴实:最 bad 的那个进程就是那个最占用内存的进程。

 6、oom_kill.c 代码里可以看到 oom_badness() 给每个进程打分,根据 points 的高低来决定杀哪个进程,这个 points 可以根据 adj 调节,root 权限的进程通常被认为很重要,不应该被轻易杀掉,所以打分的时候可以得到 3% 的优惠(adj -= 30; 分数越低越不容易被杀掉)。我们可以在用户空间通过操作每个进程的 oom_adj 内核参数来决定哪些进程不这么容易被 OOM killer 选中杀掉。比如,如果不想 MySQL 进程被轻易杀掉的话可以找到 MySQL 运行的进程号后,调整 oom_score_adj 为 -15(注意 points 越小越不容易被杀)

0 人点赞