记一次内存泄漏问题排查

问题描述
某应用上线几天后,出现了访问速度非常慢的情况,通过日志发现是堆内存溢出错误:java.lang.OutOfMemoryError: Java heap space。但是为什么会内存溢出呢?这个应用按说不需要太多内存。实在百思不解,于是进行了下面的排查:
先看一下进程的资源使用情况:

top
记一次内存泄漏问题排查_第1张图片
1.png

果然cpu飙得厉害,没猜错的话应该是频繁full gc导致的,于是看一下gc情况:

jstat -gcutil 1 5000
2.1.png

这不看不知道,一看吓一跳啊!FullGc 25万多次,Full Gc用时9万多秒,这样的程序不慢才怪啊。是什么原因导致这么频繁的full gc呢?能不能再深入查一查呢?
于是用下面命令生成一个dump文件:

jmap -dump:live,file=dump_001.bin 1

启动本地jvisualvm,再把Dump文件下载后导入到jvisualvm中:


记一次内存泄漏问题排查_第2张图片
3.png

果然看到了内存占用情况,但Byte[]是什么鬼实在不明白?那就再找找别的对象看看:


记一次内存泄漏问题排查_第3张图片
4.png

记一次内存泄漏问题排查_第4张图片
5.png

找到了kafka相关,what?难道kafka有bug?不应该吧?还是去看看这个项目跟kafka有关的代码是怎么写的吧。既然提示是channel那应该跟连接有关,就顺着这个思路找下去,果然发现了问题:


记一次内存泄漏问题排查_第5张图片
6.png

记一次内存泄漏问题排查_第6张图片
7.png

简单分析一下这位同学写的代码,就是通过redis里的key循环去发kafka消息,结果每次都创建了一个kafka的producer对象,而且该方法是static的,不能释放掉,所以就造成了内存泄漏。
结束语:平时写程序时还是要谨慎一些,平时还是需要去理解jvm内存结构,这样自己写的代码可以做到心中有数,不至于造成大问题。

你可能感兴趣的:(记一次内存泄漏问题排查)