前段时间有一次晚上系统版本升级,隔天回来后发现系统开始不稳定了,很多接口都报服务不可用,遂跟全组同事一起分析。

经排查,服务器上很多机器的CPU都飙的很高,内存使用量也一直降不下来,初步怀疑是哪里代码异常,导致堆栈内存居高不下,这种情况我们可以使用内存分析工具mat来分析程序的内存分布情况,mat是一个很简单的工具,在window下只要把生成的堆文件用mat打开就可以清晰的看到内存分布情况了。

windows版本

  1. 下载mat工具:http://www.eclipse.org/mat/downloads.php
  2. 先在cmd运行jps获取进程的pid,如7584
  3. 执行命令生成内存文件
    jmap -dump:format=b,file=heap.bin 1345
    TIM截图20191117151939
  4. 在mat中打开就可以看到各种内存信息了
    在Dominator Tree中按对象大小从上到下展示对象信息,可以很方便的定位那些占用大的对象
    TIM图片20191117152335

linux版本

因为生产环境一般都是linux的,而生产上的dump文件一般都是GB级别以上的,如果直接把生产的文件来到本地来分析,太耗费时间了,那么我们其实可以用linux版本的mat,直接在上面分析dump文件,生成的分析报告也就几个kb,再把报告拉到本地查看。

  1. 下载mat工具。
    根据jdk版本下载对应的mat工具,我生产上的jdk是1.7的,所以下载的是1.7的mat
    wget http://ftp.jaist.ac.jp/pub/eclipse/mat/1.7/rcp/MemoryAnalyzer-1.7.0.20170613-linux.gtk.x86_64.zip
    解压后配置mat的内存大小,内存需大于dump文件,不然会报内存不足
    vi MemoryAnalyzer.ini
-Xmx5024m 
  1. 获取进程的内存转储文件。
    先执行ps -ef|grep java获取进程的pid
    再执行jmap -dump:format=b,file=heap.bin PID得到dump文件
  2. 生成分析报告。
    在mat目录下执行./ParseHeapDump.sh heap.bin org.eclipse.mat.api:suspects org.eclipse.mat.api:overview org.eclipse.mat.api:top_components
    稍等片刻后会生成以下三个zip文件,这时候就可以拉到本地查看了
heap_Leak_Suspects.zip
heap_System_Overview.zip
heap_Top_Components.zip
  1. 在本地打开heap_Leak_Suspects.zip中的index.html文件。
    可以看到有一个进程的内存占用已经达到3.4个G了
    TIM截图20191117154801
    点击See stacktrace进去查看详细,看到这里有一个sql的查询,回头查看代码,发现这条SQL在版本升级是有同事不小心把where条件去掉了,导致了每次进来都是全表查询,而这张表的数据量已经是八千万级别了
    TIM图片20191117154919

至此,这次生产事故的内存已经分析顺利结束。