使用JDK工具檢查運行系統是否存在內存泄露

轉自:http://crane-ding.iteye.com/blog/715450  

  首先在實驗之前,先給大家介紹幾個jdk自帶的工具: 

1. jps  查看所有java進程的pid的命令,與Unix的ps命令類似 

2. jmap 打印出某個java進程(使用pid)內存內的所有‘對象’的情況 

3. jhat 主要用於分析jmap產生的dump並提供web頁面查看分析結果 

4. jconsole 可以查看堆內存、線程、類和CPU狀況 

        爲了實驗,所以必須先寫一段存在內存泄露的代碼,代碼如下: 
Java代碼  收藏代碼
  1. /** 
  2.  * 內存泄露測試 
  3.  * @author crane.ding 
  4.  */  
  5. public class MemoryLeakDemo {  
  6.   
  7.     static List<int[]> cache = new ArrayList<int[]>();  
  8.       
  9.     public static void main(String[] args) throws InterruptedException {  
  10.         Thread.currentThread().setName("Memory Leak Thread");  
  11.           
  12.         do {  
  13.             cache.add(new int[1024 * 50]);// 50Kb  
  14.               
  15.             Thread.sleep(500);  
  16.         } while(true);  
  17.     }  
  18.   
  19. }  

        首先運行MemoryLeakDemo,然後進行控制檯,使用jconsole命令來觀察其運行情況 
命令代碼  收藏代碼
  1. # jconsole  


圖一 


        如圖一,可以看出內存是一直往上升的,點擊‘執行gc’按鈕,效果不明顯,還是繼續上升,從這裏可以看出點小問題。這是我們可以使用jmap來打印其內存對象的情況,和使用jhat顯示內存和查詢內存的情況 
命令代碼  收藏代碼
  1. # jps  
  2. 3704 MemoryLeakDemo  
  3. 3280  
  4. 3768 Jps  
  5. # jmap -dump:format=b,file=heap.bin 3704  
  6. Dumping heap to D:\Program Files\Cygwin\home\crane.ding\heap.bin ...  
  7. Heap dump file created  
  8. # jhat heap.bin  
  9. Reading from heap.bin...  
  10. Dump file created Sun Jul 18 13:36:46 CST 2010  
  11. Snapshot read, resolving...  
  12. Resolving 3985 objects...  
  13. Chasing references, expect 0 dots  
  14. Eliminating duplicate references  
  15. Snapshot resolved.  
  16. Started HTTP server on port 7000  
  17. Server is ready.  

        jhat已經啓動了HTTP server在本地的7000端口,那麼我們可以通過瀏覽器來打開頁面(http://127.0.0.1:7000/),我們可能需要花一些時間就能在分析解釋中找到問題,com.craneding.MemoryLeakDemo類中有一個變量名爲cache的ArrayList,保存了大量的int數組,我們在結合代碼,查找操作該對象的代碼,從而發現代碼的問題。這就是一次簡單的實驗,經過這次實驗,我發現jhat顯示的分析結果還不是很直觀,後來發現原來eclipse用一個查看jmap結果的插件Memory Analyzer(http://download.eclipse.org/mat/1.0/update-site/),安裝了之後,eclispe可以直接打開heap.bin文件如下圖: 


        點擊‘Problem Suspect 1’中的‘Detail’,查看詳情,這個時候就可以很直觀的看到對象的情況了,如下圖: 

        圖中清楚的顯示了ArrayList裏面的對象和對象的佔用內存大小等情況,從而再結合代碼去查找問題,很快就能找到問題。 

        在條件允許的條件下,使用Memory Analyzer來分析jmap的分析結果會比較直觀。 


     注意如果Dump文件太大,可能需要加上-J-Xmx512m這種參數指定最大堆內存,即jhat -J-Xmx512m -port 9998 heap.bin。然後就可以在瀏覽器中輸入主機地址:9998查看了:


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