Change Dir

          先知cd——熱愛生活是一切藝術的開始

          導航

          <2015年8月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          23242526272829
          303112345

          公告

          寫下來的都是資源,分享給互聯網~~均屬原創隨筆。
          轉載引用請注明作者changedi。
          喜歡應用研究,熱愛編程,歡迎交流。

          隨筆分類(125)

          隨筆檔案(123)

          統計

          留言簿(18)

          積分與排名

          “?!眰兊牟┛?/h3>

          各個公司技術

          我的鏈接

          淘寶技術

          閱讀排行榜

          評論排行榜

          使用MAT對java內存分析

          這是一篇閱讀MAT helper的筆記。

          Heap dump
          java進程在特定時間的一個內存快照。通常在觸發heap dump之前會進行一次full gc,這樣dump出來的內容就包含的是被gc后的對象。

          dump文件包含的內容:

          1,全部的對象:類,域,原生值和引用;

          2,全部的類:classloader,類名,超類,靜態域;

          3,GC root:被JVM定義的可觸達的對象;

          4,線程棧和本地變量:線程的call stack,本地對象每幀的信息。

          dump文件不包含內存的分配信息,因此無法查詢誰創建了哪個對象這樣的信息。

          Shallow heap是一個對象占用的內存空間,一個對象需要32或者64bits。

          Retained set of XX在被jvm gc回收后被remove的一組object。

          Retained heap of X是在retained set of X中的所有對象的shallow heap size的和。換句話說就是保持X活著需要的內存空間。

          通俗的講,shallow heap是一個對象在內存中的實際空間,而retained heap是一個對象被gc回收后內存釋放出來的空間。

           


           

          這張圖可以看懂什么是leading set什么是retained set

           

          Dominator tree:定義一個對象x dominate 對象y,當每一條從root開始到y的路徑都經過x。說白了就是只要有y對象的存活,那么一定會有一個x對象。Dominator tree就是將對象引用圖轉換成的樹形結構。幫助發現在對象間保持alive的依賴,同時也能識別出retained內存的最大的chunk。Immediate dominator x of y是離y最近的dominator。

          Dominator tree有幾個屬性:

          1,對象x的子樹包含的對象(x dominate的對象集),代表了xretained set;

          2,如果xyimmediate dominator,那么ximmediate dominator同樣dominate y,以此類推;

          3,dominate tree中的邊不代表對象引用圖里對應的邊,并非嚴格的直接的對象引用。

           


           

          這張圖反應了一個對象引用圖轉換成dominator tree的示例。

           

          Gc root:一個gc根就是一個對象,這個對象從堆外可以訪問讀取。以下一些方法可以使一個對象成為gc根。

          1System class:被bootstrap或者system類加載器加載的類,比如rt.jar里的java.util.*;

          2,JNI localnative代碼里的local變量,比如用戶定義的JNI代碼和JVM的內部代碼;

          3,JNI globalnative代碼里的global變量;

          4,Thread block:當前活躍的線程block中引用的對象;

          5Thread:已經啟動并且沒有stop的線程;

          6busy monitor:被調用了wait()或者notify()或者被synchronized同步的對象,如果是synchronized方法,那么靜態方法指的類,非靜態方法指的是對象;

          7,java locallocal變量,比如方法的入參和方法內創建的變量;

          8,native stacknative代碼里的出入參數,比如file/net/IO方法以及反射的參數;

          9,finalizable:在一個隊列里等待它的finalizer 運行的對象;

          10unfinalized:一個有finalize方法的對象,還沒有被finalize,同時也沒有進入finalizer隊列等待finalize;

          11,unreachable:不會被觸碰到的對象,在MAT里被標記為root用來retain object,否則是不會在分析中出現的;

          12,java stack framejava棧幀包含了本地變量,當dump被解析時且在preferences里設置過把棧幀當做對象,這時才會產生;

          13,unknown:位置的root類型。

           

          接下來是一些獲取dump的方法:

          1,在oomdumpJVM參數:-XX:+HeapDumpOnOutOfMemoryError

          2,交互式環境下dump

          1JVM參數:-XX:+HeapDumpOnCtrlBreak

          2)用外部toolsjmap -dump:format=b,file=<filename.hprof> <pid>

          3)用外部toolsjconsole

          4)用外部工具:MAT

          5kill -3 <pid>

          6jstack -l <pid> > <dumpfile>

           

          一些排查方法:

          1,通過top consumers查找大對象,可以按照class、classloaderpackage進行group by;

          2,通過immediate dominator找到責任對象,對于快速定位一組對象的持有者非常有用,這個操作直接解決了“誰讓這些對象alive”的問題,而不是“誰有這些對象的引用”的問題,更直接高效;

          3,運行classloader分析,這個重要性體現在亮點:第一,應用使用不同的classloader加載類,第二,不同classloader加載的類存儲在不同的永久代,這理論上也是可以被回收的。當有一個類被不同的classloader加載時,這時要根據各自loader下的instance數量判斷哪個loader更重要,從而要把另一個回收掉;

          4,分析線程,本身heap dump里包含了thread信息,可以通過MAT來查看threads overviewdetail,detail中有線程的堆內存信息,也有線程棧,同時還包含了操作系統本地棧。假設不做heap dump,我們檢查到系統有問題,如何通過線程的角度來排查呢?首先top -H -p <pid>以線程的模式查看java應用的運行情況,找到占用cpu或者內存大的線程,記錄線程id,然后printf %x <tid>轉為16進制,再jstack -l <pid> > thread.logjava進程的thread dump出來,從里面找到tid,分析是哪個線程占用了系統資源。

          5,分析java容器類,因為java的容器類是最常用來存儲對象的,所以理論上發生內存泄露的風險也最高??梢詮膸讉€角度來看:1array填充率查詢(填充率fill ratio是數組中非空元素的比例),打印非原生類型數組的填充率頻率分布,從而排查系統中array的利用率;2)數組按照size分組查詢,打印一個按size分組的直方圖;3collection的填充率查詢,ArrayList/HashMap/Hashtable/Properties/Vector/WeakHashMap/ConcurrentHashMap$Segment;4collection按照size分組直方圖;5)查看一個list里的所有對象;6)查看hashmap里的所有對象;7)查看hashset里的對象;8)檢查map的碰撞率;9)檢查所有只有一個常量的array

          6,分析Finalizer,1)查詢finalizer正在處理的對象;2)查詢finalizer準備處理的對象;3)直接查看finalizer線程;4)查看finalizer線程的thread local對象。

          posted on 2015-08-17 19:08 changedi 閱讀(7473) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 蕲春县| 石景山区| 汝城县| 开远市| 田东县| 曲麻莱县| 许昌市| 古交市| 威远县| 正定县| 常德市| 石屏县| 清苑县| 秀山| 红桥区| 绍兴市| 宜宾市| 阿拉尔市| 闻喜县| 崇礼县| 五峰| 新龙县| 宁陵县| 陈巴尔虎旗| 中江县| 新建县| 淮南市| 广西| 湖北省| 唐山市| 古丈县| 大港区| 县级市| 濮阳县| 和田市| 孙吴县| 铜陵市| 慈利县| 潼南县| 沙田区| 普洱|