使用MAT对Java程序进行内存分析之小试牛刀

摘要

今天在写爬虫的时候发现数据抓到五十万左右时候,进程占用内存1.5G左右,程序完全卡死了。爬虫是用 WebMagic 框架写的,逻辑也不复杂,看不出什么问题;阅读了 WebMagic 的源码,看着也没有什么问题。就尝试通过内存分析的方式看看能否找出问题的原因。

启动程序,打开 %JAVA_HOME%/bin/jconsole.exe 工具,根据进程ID连接到运行中到Java程序

enter image description here

可以看到程序在执行过程中不断的占用内容,然后被GC回收内存。

程序初始化的时候读取了大概五十万条左右数据,所以一开始就占用了500M左右的内存,后续GC回收时,一般在500M左右徘徊

enter image description here

随着程序执行时间不断累积,可以看到内存占用越来越大了,GC回收后相对于初始化时,仍然有一百多M没有回收掉

enter image description here

运行了大概半个小时之后程序挂,在运行期间使用 jmap 工具保存了若干个时间节点下的内存快照。

1
2
3
4
5
6
7
8
9
10
11
12
13
C:\Java\jdk1.8.0_151\bin>jmap  -dump:format=b,file=D:/jvmdump/heap.bin 4344
Dumping heap to D:\jvmdump\heap.bin ...
Heap dump file created

C:\Java\jdk1.8.0_151\bin>jmap -dump:format=b,file=D:/jvmdump/heap.bin 4344
Dumping heap to D:\jvmdump\heap.bin ...
File exists

...

C:\Java\jdk1.8.0_151\bin>jmap -dump:format=b,file=D:/jvmdump/heap10.bin 4344
Dumping heap to D:\jvmdump\heap10.bin ...
Heap dump file created

jmp 工具生成的是内存快照,因此每个文件的大小就是当前程序所使用内存的大小。

接下来使用 MAT(Memory Analyzer Tool)工具对内存进行分析。

MAT工具下载地址:http://www.eclipse.org/mat/downloads.php

对比查看不同时间段占用内存最大的对象情况。

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

通过这个对比分析,可以很明显看到内存占用最大的对象是数据库连接对象,结合我的程序,能够判断出来应该是使用的数据连接池有问题。更换一个连接池测试一下发现,确实是这个问题。这样,就未完成了一次简单的内存分析。