JAVA内存泄漏解决日记

最近解决了一次线上内存泄漏的BUG,将解决问题的过程记录如下:

1.登录服务器查询JAVA进程heap的概要信息,使用命令:jmap –heap 3772,结果如下图所示:


JAVA内存泄漏解决日记_第1张图片

从上图可见,老年代已使用99%,这时JVM会不停的GC,GC时会Stop-the-world,当Stop-the-world发生时,除了GC所需的线程以外,所有线程都处于等待状态,直到GC任务完成。如果老年代已使用99%,这时基本大部分时间都在GC,所以应用也就无法正常提供服务。

2.查询JAVA进程每个class的实例数目,使用命令:jmap –histo:live 3772,结果如下图如示:


JAVA内存泄漏解决日记_第2张图片

通过上述命令基本可以定位到实例数目异常的class,定位到异常的class后,有的时候,仅仅通过review源代码,就可以定位到问题所在,但这种情况很少发生,大部分情况都是定位不到问题所在,这时就要查找这些实例的Paths from GC Roots,这样才能定位到这些实例被哪些对象所持有,从而导致的内存泄漏。

我使用的Java profiler工具是yourkit java profiler,操作过程如下,安装及配置yourkit

java profiler的过程暂时不表,这里我只说通过工具如何查找对象的Paths from GC

Roots。

3.点击yourkit java profiler工具栏上Capture Memory Snapshot按钮,会生成JAVA进程heap的一个快照。


4.选择创建的快照,并点击上面的Memory页签以及ObjectExplorer页签,右键点击下面的实例,就可以查看Paths from GC Roots。


JAVA内存泄漏解决日记_第3张图片

5.查看对象Paths from GC Roots的界面如下图所示,即可准确定位到内存泄漏的点。


JAVA内存泄漏解决日记_第4张图片

以上仅仅是一个粗略的记录,解决问题的过程其实是花费了整整一天的时间才定位到内存泄漏的点,因为是第一次,很多问题要自己摸索,所以比较慢,如果再遇到类似问题,问题的过程应该会快很多,所以对本次过程也做一个粗略的记录,希望可以给其它同学以启发。

如果有想了解细节的同学,欢迎留言或私信沟通。

你可能感兴趣的:(JAVA内存泄漏解决日记)