思路

①、Java应用程序的问题:发生OOM导致进程Crash

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

  • Step1: 查看JVM参数 -XX:+HeapDumpOnOutOfMemoryError 和 -XX:HeapDumpPath=*/java.hprof;
  • Step2: 根据HeapDumpPath指定的路径查看是否产生dump文件;
  • Step3: 若存在dump文件,使用Jhat、VisualVM等工具分析即可;

②、JVM出错:JVM或JDK自身的Bug导致进程Crash

当JVM出现致命错误时,会生成一个错误文件 hs_err_pid.log,其中包括了导致jvm crash的重要信息,可以通过分析该文件定位到导致crash的根源,从而改善以保证系统稳定。
当出现crash时,该文件默认会生成到工作目录下,然而可以通过jvm参数-XX:ErrorFile指定生成路径。

③、被操作系统OOM-Killer

Step1: 查看操作系统日志:确定Java进程是否被操作系统Kill;
sudo grep –color “java” /var/log/messages

  • Step2: 若被操作系统Kill,执行dmesg命令查看系统各进程资源占用情况,明确Java占用内存是否合理,以及是否有其它进程不合理的占用了大量内存空间;

4、内存占用过高的线程当流氓线程处理(kill)

排查过程

先查询当前服务器是否内存情况。

  1. free -h

以下命令可以查询系统kill掉日志

  1. 当天日志: egrep -i 'killed process' /var/log/messages
  2. 全部日志: egrep -i -r 'killed process' /var/log

如果出现记录,则可以确定系统自动kill过线程。

解决方案

1、 优化程序,减少内存占用。 2、 增加服务器内存。(当我没说 🙄️) 3、 增加 swap 分区(参考 CentOS 添加Swap空间) 4、 修改/proc/sys/vm/overcommit_memory设置,kernel 文档

简单介绍
  1. 0: heuristic overcommit (this is the default)
  2. 1: always overcommit, never check
  3. 2: always check, never overcommit
  • 为0时:启发式oom,即当申请的虚拟内存不是很夸张的大于物理内存,则系统允许申请,但是当进程申请的虚拟内存很夸张的大于物理内存,则就会产生 OOM。
  • 为1时:全部允许overmemory内存申请,不管你多大的虚拟内存申请都允许,当系统内存耗尽时,才会产生oom。
  • 为2时:不能超出限定额的内存申请,(/proc/sys/vm/overcommit_ratio,默认50%),如果超出限制,产生oom
    设置方法
    1. vim /etc/sysctl.conf
    2. vm.overcommit_memory = 1
    使配置生效
    1. sysctl -p