一、背景说明

在一次大批量数据测试时,一个Java服务模块突然宕掉,并且连续出现了好几次。检查服务已经开启了打印堆栈信息-XX:+HeapDumpOnOutOfMemoryError,
但是在服务器运行目录下并没有发现.hprof文件生成。服务器总内存为16G,当前Java服务设置的内存为:-Xms5000M -Xmx8000M

二、原因分析

Java进程突然被干掉无外乎以下三种情况:

  • Linux OOM killer 杀死了Java进程
  • JVM自身故障
  • JVM OOM导致进程退出

2.1 Linux 的OOM killer

Linux内核有一个OOM(out of memory) killer机制,当系统内存严重不足时,OOM killer会选择一个或多个进程杀死。关于OOM killer机制可参考上一篇文章Linux中的CommitLimit与OOM Killer.。
因此,当java进程突然消失时,首先怀疑是不是被OOM killer杀掉了。

查看系统日志文件/var/log/messages

$egrep -i 'killed process' /var/log/messages
Nov 19 16:24:31 localhost kernel: Killed process 26980 (java) total-vm:14316628kB, anon-rss:6138236kB, file-rss:0kB, shmem-rss:0kB

查看linux系统内核日志

$dmesg | grep java
[3571149.337671] Out of memory: Kill process 26980 (java) score 243 or sacrifice child
[3571149.338458] Killed process 26980 (java) total-vm:14316628kB, anon-rss:6138236kB, file-rss:0kB, shmem-rss:0kB
[3571149.395860] java: page allocation failure: order:0, mode:0x201da
[3571149.395864] CPU: 0 PID: 26980 Comm: java Kdump: loaded Tainted: G             L ------------ T 3.10.0-957.el7.x86_64 #1

2.2 JVM的自身故障

当JVM发生致命错误导致崩溃时,会生成一个hs_err_pid_xxx.log这样的文件,该文件包含了导致 JVM crash 的重要信息,我们可以通过分析该文件定位到导致 JVM Crash 的原因,从而修复保证系统稳定。
默认情况下,该文件是生成在工作目录下的,当然也可以通过 JVM 参数指定生成路径:

-XX:ErrorFile=/var/log/hs_err_pid<pid>.log

这个文件主要包含如下内容:

  • 日志头文件
  • 导致 crash 的线程信息
  • 所有线程信息
  • 安全点和锁信息
  • 堆信息
  • 本地代码缓存
  • 编译事件
  • gc 相关记录
  • jvm 内存映射
  • jvm 启动参数
  • 服务器信息

2.3 JVM的OOM

JVM由于有GC机制,一般很少发生OOM,但是如果出现内存泄露,就可能发生OOM导致java进程退出。
可以根据JVM的下面两个参数查找堆内存快照文件定位问题。

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=*/java.hprof

找到dump快照文件,借助一些MAT或VisualVM这一类可视化工具分析问题原因。

三、总结

当java进程突然消失时,可以先查看是否有dump文件;如果没有dump文件,再查看是否有hs_err_pid.log日志;如果也没有,则查看内核日志。

参考文章

JAVA进程突然消失的原因?
JVM致命错误日志(hs_err_pid.log)分析