Java教程

一次OOM排查的详细经过

本文主要是介绍一次OOM排查的详细经过,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

1.问题定位

预发环境机器出现访问502的问题。

登录机器查看日志,没有发现特别的日志。

考虑到QA刚刚在做压测,想到是不是出现了OOM问题。搜索错误日志:

cat error.log | grep "OutOf" 

果然有OOM错误日志:

java.lang.OutOfMemoryError: GC overhead limit exceeded
java.lang.OutOfMemoryError: GC overhead limit exceeded

锁定是出现OOM问题。

2.查看PID

使用命令

jps -lvm

列出当前机器所有运行中的JVM进程。找到Web服务对应的进程,拿到你进程ID。

3.查看堆信息

jmpa -heap 1207

在这里插入图片描述
可以看到整个堆的最大值为1G,MaxHeapSize 1024M。其中老年代683,年轻代340。整体配置偏小,接下来就是确定是由于配置的内存偏小,导致的OOM,还是有其他内存泄漏导致的。

4.查看是哪些对象占用了内存

使用jmap -histo PID命令查看堆中对象的占比。

jmap -histo 1207

因为对象种类一般来说较多,可以将上述命令的输出存入文件,方便后续查看。

jmap -histo 1207 > obj.txt

之后可以使用less等命令查看:

less obj.txt

在这里插入图片描述
输出结果中instances表示对象个数,bytes表示占用内存的字节数。其中最多的是[C,这个[表示的数组的意思。C表示char,合起来就是字符数组char[],字符串String底层使用字符数组存储,这个一般说明有大量的字符串。不过这也说明不了啥,一般项目都是字符串较多。

另外看到数量较多有HashMap的Node节点。这个自然就是HashMap,这个需要查一下看是哪块逻辑在用。项目用了Caffine缓存看了底层是ConcurrentHashMap存储的,不知道这么多HashMap是做什么的?
有3万多个HashMap不知道是干啥的?

5.使用MAT进行一步分析堆转储文件

上一步使用jmap -dump:live生成了堆转储文件,但是只能看到对象的数量和占用空间大小。对于HashMap、String等Java对象并不知道具体和什么业务相关。为了进一步分析还需要使用MAT。

https://blog.csdn.net/weixin_39850150/article/details/111250003

没有MAT时,也可以用jhat进行分析。
jhat为java自动的堆转储文件分析工具,特点是使用简单,不需要额外安装。
使用如下命令启动jhat

jhat dump.bin

其中dump.bin为堆转储文件。之后会启动一个http服务来查看分析结果,访问localhost:7000来进行查看。
默认进来展示了所有非Java原生类的情况,页面拉到最下面还有其他的页面可以查看:
在这里插入图片描述

6.分析结果

分析发现没有内存泄漏,单纯是内存设置过小导致的OOM。使用-Xmx6g 设置最大堆内存为6g,使用-Xms6g设置堆最小内存为6g,即进程启动后直接申请6g的内存使用。使用-Xmn2g设置年轻代大小为2g。

这篇关于一次OOM排查的详细经过的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!