轉自: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狀況
爲了實驗,所以必須先寫一段存在內存泄露的代碼,代碼如下:
- /**
- * 內存泄露測試
- * @author crane.ding
- */
- public class MemoryLeakDemo {
- static List<int[]> cache = new ArrayList<int[]>();
- public static void main(String[] args) throws InterruptedException {
- Thread.currentThread().setName("Memory Leak Thread");
- do {
- cache.add(new int[1024 * 50]);// 50Kb
- Thread.sleep(500);
- } while(true);
- }
- }
首先運行MemoryLeakDemo,然後進行控制檯,使用jconsole命令來觀察其運行情況
- # jconsole
圖一
如圖一,可以看出內存是一直往上升的,點擊‘執行gc’按鈕,效果不明顯,還是繼續上升,從這裏可以看出點小問題。這是我們可以使用jmap來打印其內存對象的情況,和使用jhat顯示內存和查詢內存的情況
- # jps
- 3704 MemoryLeakDemo
- 3280
- 3768 Jps
- # jmap -dump:format=b,file=heap.bin 3704
- Dumping heap to D:\Program Files\Cygwin\home\crane.ding\heap.bin ...
- Heap dump file created
- # jhat heap.bin
- Reading from heap.bin...
- Dump file created Sun Jul 18 13:36:46 CST 2010
- Snapshot read, resolving...
- Resolving 3985 objects...
- Chasing references, expect 0 dots
- Eliminating duplicate references
- Snapshot resolved.
- Started HTTP server on port 7000
- 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查看了: