Spring & JVM

JVM 进程异常退出分析及处理

1.启动失败异常退出

  • 1.1 如果是 ClassNotFoundException 的错误导致退出,多半是jar包冲突,找出冲突jar排除即可,可增加 JVM 启动参数打印加载情况。
java -XX:+TraceClassLoading ...

2.运行中异常退出

2.1 Java 程序的问题导致发生OOM导致进程Crash

最常见的是发生堆内存异常“java.lang.OutOfMemoryError: Java heap space”,排查步骤如下:

  • Step1: 查看JVM参数-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/mnt/disk1/log/myapp/dump.hprof

  • Step2: 根据HeapDumpPath指定的路径查看是否产生dump文件;

  • Step3: 若存在dump文件,使用Jhat、VisualVM等工具分析即可;

2.2 JVM出错或JDK自身的Bug导致进程Crash

当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 被操作系统 OOM-Killer

  • Linux 内核有个机制叫OOM killer(Out-Of-Memory killer),该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了防止内存耗尽而内核会把该进程杀掉。因此,你发现java进程突然没了,首先要怀疑是不是被linux的OOM killer给干掉了!
egrep -i 'killed process' /var/log/messages
# 或
grep “Out of memory” /var/log/messages
# 结果如:
Oct  8 19:21:46 web-node2 kernel: Out of memory: Kill process 20148 (java) score 98 or sacrifice child
Oct  8 19:21:46 web-node2 kernel: Killed process 20148 (java) total-vm:7897848kB, anon-rss:1590688kB, file-rss:4204kB, shmem-rss:0kB
  • 还可去内核日志查, 有时Linux系统或者系统上运行的java或者其它进程,会发生一些莫名其妙的问题,比如突然挂掉了,比如突然重启等等。在软件上找不到问题所在,此时我们应该怀疑硬件或者内核的问题,此时可使用 dmesg来检查killed日志:
# 按时间格式显示 java 有关的日志
dmesg -T | grep "(java)"
# 或
dmesg -T | grep 'Out of memory'

然后再对比java日志停止时间,看来这里才是问题的根源,所以接下来从优化java内存占用、加内存入手尝试解决问题吧。

dmesg 命令是用来在Unix-like系统中显示内核的相关信息的。dmesg全称是display message (or display driver),即显示信息, 实际上,dmesg命令是从内核环形缓冲区中获取数据的。当我们在Linux上排除故障时,dmesg命令会十分方便,它能很好地帮我们鉴别硬件相关的error和warning。除此之外,dmesg命令还能打印出守护进程相关的信息,已帮助我们debug。

参考 1: linux 内核 OOM score 是咋算出来的

留言

您的电子邮箱地址不会被公开。