摘要
今天在写爬虫的时候发现数据抓到五十万左右时候,进程占用内存1.5G左右,程序完全卡死了。爬虫是用 WebMagic 框架写的,逻辑也不复杂,看不出什么问题;阅读了 WebMagic 的源码,看着也没有什么问题。就尝试通过内存分析的方式看看能否找出问题的原因。
启动程序,打开 %JAVA_HOME%/bin/jconsole.exe 工具,根据进程ID连接到运行中到Java程序
可以看到程序在执行过程中不断的占用内容,然后被GC回收内存。
程序初始化的时候读取了大概五十万条左右数据,所以一开始就占用了500M左右的内存,后续GC回收时,一般在500M左右徘徊
随着程序执行时间不断累积,可以看到内存占用越来越大了,GC回收后相对于初始化时,仍然有一百多M没有回收掉
运行了大概半个小时之后程序挂,在运行期间使用 jmap 工具保存了若干个时间节点下的内存快照。
1 | C:\Java\jdk1.8.0_151\bin>jmap -dump:format=b,file=D:/jvmdump/heap.bin 4344 |
jmp 工具生成的是内存快照,因此每个文件的大小就是当前程序所使用内存的大小。
接下来使用 MAT(Memory Analyzer Tool)工具对内存进行分析。
MAT工具下载地址:http://www.eclipse.org/mat/downloads.php
对比查看不同时间段占用内存最大的对象情况。
通过这个对比分析,可以很明显看到内存占用最大的对象是数据库连接对象,结合我的程序,能够判断出来应该是使用的数据连接池有问题。更换一个连接池测试一下发现,确实是这个问题。这样,就未完成了一次简单的内存分析。