jprofiler 查看程序內存泄露


在最近的工作中,通過JProfiler解決了一個內存泄漏的問題,現將檢測的步驟和一些分析記錄下來,已備今后遇到相似問題時可以作為參考。

運行環境:

Tomcat6,jdk6,JProfiler8

內存泄漏的現象:

1. 在服務器中執行某些批量操作的時候,發現內存只升不降;就算gc后,內存也不能被完全釋放;
2. 除非重啟tomcat服務器,內存永遠不會被釋放,反復執行這些操作,會導致無可用內存,tomcat死掉;

使用JProfiler檢查內存泄漏的步驟:

1. 初始化檢驗環境:

切換到“Live Memory-->All Objects”標簽,可以看到當前tomcat中的對象情況。

在執行操作前,需要先運行“Run GC”,使jvm進行內存回收,清理無效的對象;

為了便於比較內存的增長情況,可以點擊"Mark Current"按鈕,來將當前內存使用情況作為參照;

 點擊后會顯示“Difference”列,該列會列出對象數量的變化和變化比率;

2.打開內存記錄:

點擊“Start Recordings”按鈕,開始記錄。執行這步的主要目的是為下面“Heap Walker”,設置一個監控區間;如果不記錄的話,“Heap Walker”將分析jvm虛擬機的所有內存,即耗時又不能准確的發現內存泄漏的原因。

3. 執行操作,執行gc;

執行會引起內存泄漏的操作,執行完進行內存回收;

 可以點擊下面的“update”按鈕,進行視圖的更新;

 

執行內存回收后,仍然存在於內存中的對象有可能是泄漏的對象;如下圖,instance count中紅色的部門為不能回收的對象,difference列列出了增加的對象數量和增幅;以String為例,在該操作中增加了31751個對象,增幅達到了14%,隨后會在HeapWalker中觀察這些對象,分析哪些對象是泄漏的;

一般引起泄漏的對象包括:String,char[],HashMap等,這些對象需要重點關注下;

4. 關閉內存記錄:

點擊“Stop Recordings”關閉內存記錄,告訴jProfiler把這段記錄作為分析對象;

5. 找到增加迅速的對象類型,打開HeapWalker:

在視圖中找到增長快速的對象類型,一般包括String、char[]、Map等;

在這個操作中,String的增長速度很快。在Liver memory視圖中找到String,點右鍵,選擇“Show Selectiion In Heap Walker”,切換到HeapWarker 視圖;

 

切換前會彈出選項頁面,注意一定要選擇“Select recorded  objects”;這樣Heap Walker會在剛剛的那段記錄中進行分析;否則,如果不勾選的話,他會分析tomcat的所有內存對象,這樣既耗時又不准確;

 

6. 在HeapWalker中,找到泄漏的對象;

HeapWarker 會分析內存中的所有對象,包括對象的引用、創建、大小和數量;

 通過切換到References頁簽,可以看到具體的對象;

 

在這些內存對象中,找到泄漏的對象(應該被回收);可以在該對象上點擊右鍵,選擇“Use Selected Instances”縮小對象范圍;

7. 通過引用分析該對象:

在References引用頁簽中,可以看到該對象的的引用關系,可以切換incoming/outcoming,顯示引用的類型:

incoming  表示顯示這個對象被誰引用;

outcoming 表示顯示這個對象引用的其他對象;

 

選擇“Show In Graph”將引用關系使用圖形方式展現;

 

 

 

 

選中該對象,點擊“Show Paths To GC Root”,會找到引用的根節點;

 

在上圖中,我們可以發現,這個String對象最終的引用是在Thread線程中的ThreadLocalMap對象中;這給我們提供了線索,我們需要在程序中查找有關ThreadLocalMap部分的代碼,檢查為什么這個對象沒有被釋放;這往往就是泄漏的根源。

8. 通過創建分析該對象:

如果第7步還不能定位內存泄露的地方,我們可以嘗試使用Allocations頁簽,該頁簽顯示對象是如何創建出來的;
我們可以從創建方法開始檢查,檢查所有用到該對象的地方,直到找到泄漏位置;

 

內存泄漏的原因分析:

通過上面的分析,這次內存泄露主要由下面的原因造成:
有操作將對象存放在ThreadLocal的靜態變量中,引用不會被釋放,所以該對象不會被回收,一直存在於內存中,導致內存泄漏;

 

參考資料:

 1. 轉載自: https://blog.csdn.net/coslay/article/details/43270311

 2.《利用Java剖析工具JProfiler查找內存泄漏的方法》http://jingyan.baidu.com/article/9c69d48f552d5f13c9024e3b.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM