我们在处理线上问题的时候,如果遇到了程序进程突然被kill掉,可以通过下面的命令来查看程序死掉的时间:
#查看oom被kill的进程
grep "Out of memory" /var/log/messages

或者:
#查看系统日志:
egrep -i -r 'killed process' /var/log

或者:
dmesg -T| grep java

从这些日志中我们可以看到程序oom的时间,结合我们程序本身的日志,可以推算是否是自己的程序挂掉了。
一般java程序在部署的时候会在启动的脚本中加入dump信息来帮助我们迅速定位线上的问题。
例如我写个简单的程序:
public class Main {
public static void main(String[] args) {
List<byte[]> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
list.add(new byte[1024000]);
}
}
}
只要程序一运行我们很快就会发现OOM异常:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.xqnode.Main.main(Main.java:10)
从这个异常中我们会快速定位到具体的哪一行出了问题。但是在实际生产环境不会出现这么简单的代码,通常程序是在不同的包中相互调用,而且会有多线程的情况,比较难定位到具体的错误发生的代码,所以我们在启动脚本中加入dump信息,然后我们就能找到对应的问题所在了。这里我们制定dump文件输出到D盘下。
启动配置:

再次运行程序,出现OOM的时候会在D盘下看到这个文件:

然后我们使用jdk中自带的工具jvisualvm.exe打开dump文件,路径在jdk/bin下。
点击 文件 => 装入,选择后缀名,打开文件

看到的界面如下:

我们从上面的红色部分可以清晰的看到我们的程序错误在哪里。
还可以使用jmap对正在进行的程序进行分析:
jmap -dump:live,format=b,file=heap.bin <pid>

本文介绍如何通过系统日志和dump信息定位线上Java程序的OOM问题,包括使用grep、dmesg等命令查看进程被kill的时间,以及如何利用JDK自带工具如jvisualvm、jmap进行内存分析,快速定位问题根源。
1216

被折叠的 条评论
为什么被折叠?



