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
在這裏插入圖片描述
顯示
在這裏插入圖片描述

分析
在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

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