Linux下Java进程无故消失案的元凶:OOM Killer
Java进程在运行时突然挂掉,常见的原因有很多,例如代码本身的致命bug、JVM自身故障、内存泄漏触发JVM的OOM机制等,但是这些原因都属于主观原因,基本可以通过查看日志来发现。
事实上,Java进程还可能被动地结束。由于用户进程只是运行在操作系统之上的普通进程,享受着操作系统提供的资源,因此也受制于操作系统。在Linux下,就存在一个隐形的进程杀手:OOM Killer。这次通过一个案件,我们抓住了这个元凶。
案件记录
我们先来看一下案发现场:
一个普通的Spring Boot项目,被打成jar包,运行在Linux系统中。
我们可以用 ps -ef | grep java
命令在进程列表中找到它的身影:
可以看到,这个Java进程的进程号(PID)是14303。
可是突然有一天,这个进程莫名其妙消失了,在进程列表里怎么也寻找不到。
查看项目日志
我们首先尝试从项目日志中查找痕迹,但是并没有发现任何异常和错误信息。排除了代码本身bug以及内存泄漏的嫌疑。
查看JVM致命错误日志
JVM在发生致命错误时,会产生一个日志文件:hs_err_pid_<进程号>.log
,这个文件默认是在工作目录下。但是这次我们并没有发现这个文件,可以判断得出,JVM没有发生致命错误,因此嫌疑排除。
幕后黑手OOM Killer
排除了一系列主观原因后,我们可以断定Java进程是被杀掉的。
我们得知,在Linux操作系统中,一直潜藏着一个隐形的进程杀手:OOM Killer。它帮助Linux监视着内存资源,一旦内存资源即将耗尽,它就会挑出那个最占用内存的进程,然后毫不留情的杀掉它。
但是,这个杀手即使做得再漂亮,也会留下痕迹。
通过 dmesg -T | grep java
命令,我们发现了以下证据:
原来在案发时,系统的内存资源所剩不多,进程号为14303的Java进程占用内存太多,被OOM Killer挑出并杀掉了。
至此真相大白,时间、地点、人物证据俱全,OOM Killer就是Java进程无故消失案的元凶!
案件后续
经历过这个案件以后,Java进程深知它必须保护好自己,不做出头鸟。
以前占用了那么多内存,也有它自己不对的地方,以后必须要控制好内存占用。这不,它再次启动时,用 -Xmx
参数限制了自己能够占用的最大内存:
通过设置一个合理的参数,Java进程以后再也没有被莫名其妙杀掉过了。