這篇帖子只介紹利用MemoryAnalyzer進行簡單的JVM的堆的分析,至於JVM的內部結構是怎麼樣的,這裏不進行分析。好吧,廢話很少說;首先 若是咱們要分析JVM某個時刻的Heap的對象分配狀況,咱們就必需要dump這個時刻的JVM的heap(堆);有如下幾個辦法進行dump某個時刻 JVM的heap內容:java
一、 使用$JAVA_HOME/bin/jmap -dump來觸發,
eg:jmap-dump:format=b,file=/home/longhao/heamdump.out <pid>
二、 使用$JAVA_HOME/bin/jcosole中的MBean,到 MBean>com.sun.management>HotSpotDiagnostic>操做>dumpHeap中,點擊 dumpHeap按鈕。生成的dump文件在 java應用的根目錄下面。
三、在應用啓動時配置相關的參數 -XX:+HeapDumpOnOutOfMemoryError,當應用拋出OutOfMemoryError時生成dump文件。
四、使用hprof。啓動虛擬機加入-Xrunhprof:head=site,會生成java.hprof.txt文件。該配置會致使jvm運行很是的慢,不適合生產環境。app
利用MemoryAnalyzer進行Heap分析
去eclipse官網上去下載MemoryAnalyzer,能夠下載非插件版的,這樣MemoryAnalyzer運行起來比較快,若是是 eclipse插件版進行可能會致使eclipse卡死。本人下載的版本是MemoryAnalyzer-1.2.0.20120530- win32.win32.x86_64。eclipse
1、Java代碼樣例jvm
[java] view plain copy工具
2、設置JVM啓動參數
在此咱們把JVM堆的最大內存設置爲512m,而且讓程序運行過程當中出現內存溢出的時候會dump當時的JVM對內存的內容,因此須要加上 XX:+HeapDumpOnOutOfMemoryError參數;所以按照如下步驟在eclipse中加入啓動參數spa
3、運行程序
運行程序,而後觀察控制檯的輸出,輸出結果以下:.net
從以上的輸出結果來看,此程序已經拋出了OutOfMemoryError了,而且生成了一個heap文件,文件名爲java_pid3880.hprof,下一步咱們就能夠拿這個文件在MemoryAnalyzer分析了。插件
4、導入heap文件分析orm
導入後按照如下步驟執行進行內存泄露的可疑分析;對象
鼠標點擊紅色的部分會出現菜單,選中菜單的第一行的List objects > With Incoming references,就會出現如下界面
此圖展示了HashMap$Entry被引用的路徑,HashMap$Entry被一個java.util.HashMap的table實例變量引用, 而這個HashMap又被JVMOutOfMemberyErrorSimulator類變量leakingMap引用,因此經過這些路徑就很容易找到是 哪段代碼致使的內存溢出。
經過以上分析咱們就發現,類JVMOutOfMemberyErrorSimulator的leakingMap變量的內容太大致使了內存溢出,因此這樣就能很快定位到問題。
其中注意Shallow vs. Retained Heap的區別,這裏不進行解釋,點擊MemoryAnalyzer的Help菜單裏面的HelpContents就能夠查找到
這裏解釋下Java Local,JVM裏面的類變量,實例變量的名字在JVM裏面都有記錄,而局部變量是沒有記錄的,因此Java Local在這裏就表明局部變量。
總結:以上的這些分析方法是入門級別的,現實中的OOM分析確定比這更復雜,本人就曾經遇到過不少詭異的OOM。但在通常狀況下,若是出現OOM,那麼我 們確定須要對JVM的heap進行分析,這篇帖子是一個很好的思惟方法;固然你也能夠利用其餘的工具進行heap分析,但思路大概都差不 多;MemoryAnalyzer是一個不錯的工具,裏面有不少的小工具給我分析,能夠花點時間看看。