[TOC]
今天线上生产环境遇到一个内存溢出导致,内存被用完,导致db连接池爆掉的情况,下面我们主要来复盘一下故障的流程。
案例介绍
首先我们监控到我们的一个核心模块最近一个月的gc 情况(最近一个月都没有重启服务,或者模块升级)
(图:06-01.jpg)
看到上图,明显发现每次fullgc 都没有把内存给收回来的情况,存在着明显的内存泄漏的问题。
(图:06-02.jpg)
如图06-02 这样规律的波形图才是正常的gc 回收内存的过程,很明显的是在周期内发生gc 内存都能被正常回收了。
案例分析
首先我们把该机器上jmap 一下把堆信息dump 下来。 我们的到 M1-001_jmap_700.hprof 文件。
对于堆文件的分析,这里推荐mat(https://www.eclipse.org/mat/) 和 jprofiler 来进行分析。
在MemoryAnalyzer.ini
中增加或编辑以下值,防止Java heap space:
-vmargs
-Xmx2g
-XX:-UseGCOverheadLimit
jprofiler 分析
步骤1:打开.hprof 文件
2:双击第一个大对像
看到这个一直被引用的对象,然后翻看代码
是某个打印日志的组件在打印日志后,没执行pop,才导致这个一直套娃的链表大对像。
java dump
java dump 主要分2种,一个是内存dump,一个是线程dump 。
内存dump 可以执行 jmap 如:
jmap -dump:live,format=b,file=xxxheap-jmap.hprof 【pid】
线程dump 可以执行 jstack
jstack -l 【pid】 > 1.txt