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應用程序佔用的內存出現了泄露的跡象,那麼我們一般採用下面的步驟分析:
- 用工具生成java應用程序的heap dump(如jmap)
- 使用Java heap分析工具(如MAT),找出內存佔用超出預期的嫌疑對象
- 根據情況,分析嫌疑對象和其他對象的引用關係。
- 分析程序的源代碼,找出嫌疑對象數量過多的原因
demo
- 獲取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
- 利用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
- 如果上面一步還無法定位到關鍵信息,那麼需要拿到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
- 拿到heap dump文件,利用MAT來分析heap profile
安裝MAT插件(下載https://www.eclipse.org/mat/downloads.php)
解壓 右擊打開顯示包內容
打開MemoryAnalyzer
打開對應的heap.hprof
顯示
分析