Java内存泄漏的排查笔记

1 确定频繁Full GC现象

jps -l

jstat -gcutil 20954 1000

root@open-api-1:/openapi/2ccm# jstat -gcutil  7551 1000
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
  0.00 100.00   9.00  13.30  95.74  93.97    264    1.745     4    0.783    2.528
  0.00 100.00  12.00  13.30  95.74  93.97    264    1.745     4    0.783    2.528
  0.00 100.00  12.00  13.30  95.74  93.97    264    1.745     4    0.783    2.528
  0.00 100.00  15.00  13.30  95.74  93.97    264    1.745     4    0.783    2.528

jstat执行结果
E,表示Eden
S0、S1,表示Survivor0、Survivor1
O,表示Old
M, 表示元空间
CCS, 表示压缩类空间利用率为百分比
YGC,表示Young GC
FGC,表示Full GC
GCT,表示GC Time

2 找出导致频繁Full GC的原因

分析方法通常有两种:
1)把堆dump下来再用MAT等工具进行分析,但dump堆要花较长的时间,并且文件巨大,再从服务器上拖回本地导入工具,这个过程有些折腾,不到万不得已最好别这么干。
2)更轻量级的在线分析,使用“Java内存影像工具:jmap”生成堆转储快照(一般称为headdump或dump文件)。
jmap命令格式:
jmap [ option ] vmid

使用命令如下:
jmap -histo:live 20954

3 定位到代码

定位带代码,有很多种方法,比如前面提到的通过MAT查看Histogram即可找出是哪块代码。——我以前是使用这个方法。 也可以使用BTrace,我没有使用过。

一台生产环境机器每次运行几天之后就会莫名其妙的宕机,分析日志之后发现在tomcat刚启动的时候内存占用比较少,但是运行个几天之后内存占用越来越大,通过jmap命令可以查询到一些大对象引用没有被及时GC,这里就要求解决内存泄露的问题。

Java的内存泄露多半是因为对象存在无效的引用,对象得不到释放,如果发现Java应用程序占用的内存出现了泄露的迹象,那么我们一般采用下面的步骤分析:

  1. 用工具生成java应用程序的heap dump(如jmap)
  2. 使用Java heap分析工具(如MAT),找出内存占用超出预期的嫌疑对象
  3. 根据情况,分析嫌疑对象和其他对象的引用关系。
  4. 分析程序的源代码,找出嫌疑对象数量过多的原因

demo

  1. 获取tomcat的pid
root@open-api-1:/openapi/2ccm# jps -l
7089 open-api-service-mysql-exec.jar
6962 open-api-registry-center-exec.jar
2307 org.apache.catalina.startup.Bootstrap
7156 open-api-service-italy-exec.jar
7396 open-api-service-rabbitmq-exec.jar
12980 open-api-devops-service-exec.jar
13621 sun.tools.jps.Jps
7462 open-api-service-redis-exec.jar
13226 sun.tools.jstatd.Jstatd
7228 open-api-service-finland-exec.jar
7551 open-api-global-quartz-exec.jar
  1. 利用jmap初步分析内存映射,命令:
root@open-api-1:/openapi/2ccm# jmap -histo:live 7551 | head -100

 num     #instances         #bytes  class name
----------------------------------------------
   1:         76704       16532752  [C
   2:          2061        9877048  [J
   3:         61179        1957728  java.util.concurrent.ConcurrentHashMap$Node
   4:         20646        1816848  java.lang.reflect.Method
   5:         74914        1797936  java.lang.String
   6:         11929        1320640  java.lang.Class
   7:         19019        1183080  [Ljava.lang.Object;
   8:         24605         984200  java.util.LinkedHashMap$Entry
  1. 如果上面一步还无法定位到关键信息,那么需要拿到heap dump,生成离线文件,做进一步分析,命令:
root@open-api-1:/openapi/2ccm# jmap -dump:live,format=b,file=heap.hprof 7551
Dumping heap to /openapi/2ccm/heap.hprof ...
Heap dump file created
  1. 拿到heap dump文件,利用MAT来分析heap profile

安装MAT插件(下载https://www.eclipse.org/mat/downloads.php)

解压 右击打开显示包内容
在这里插入图片描述

打开MemoryAnalyzer

在这里插入图片描述
打开对应的heap.hprof
在这里插入图片描述
显示
在这里插入图片描述

分析
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章