結構總覽
記住下面名詞的解釋:
Shallow Heap:代表當前物件佔用的記憶體空間;
Retained Heap:代表當前物件被回收後所能釋放的記憶體空間大小。
一些操作:
List objects -> with outgoing references :列出包含哪些物件;
List objects -> with ingoing references :列出被哪些物件包含;
第一行的Regex中都可以填寫過濾表示式快速篩選自己想分析的類。
1 Detail
這部分統計了當前堆已使用的總大小
Size: 18.8 MB Classes: 8.3k Objects: 325.8k Class Loader: 119 Unreachable Objects Histogram
總大小: 18.8M 類大小8.3kb 物件:325.8k 類載入器:119k
Unreachable Objects 代表根不可達的物件,即可以被回收的物件,如下圖所示,可以發現最大的前幾位物件是char[],String,byte[]和TRNameListHitRecord物件,這是由於壓測時請求量太大,生成了大量的TRNameListHitRecord物件,在物件非同步入庫後被釋放導致。
2 Biggest Objects by Retained Size
這部分代表目前應用中最大的幾個物件的總大小,這部分的資料可以用來分析應用是否可能發生記憶體洩漏,留在後面Leak Suspects中介紹。
3 Actions
3.1 Histogram
應用中各個類所佔用記憶體大小的直方圖,倒序排列
可以看到NameList類一共有10078個,黑名單和白名單各5000個左右,佔用了241872/1024/1024=0.23M,Retained heap大小為725624/1024/1024=0.69M,符合預期。
還可以在第一行的regex裡填寫條件,此時填寫應用的包名,就可以過濾到目前應用中所有物件佔用的記憶體大小,如下圖,可以發現,沒有什麼問題,NameList是黑白名單的快取資訊,其他的數量都很少。
3.2 Dominator Tree
應用中各個物件佔比,倒序排列,可以展開某條資料檢視其內部具體包含哪些變數及變數的記憶體佔比。第一行的Regex表示式同樣可以根據自己的需要進行過濾。
可以發現系統中目前最大的物件為SynMap,它是儲存黑白名單的物件,2162040/1024/1024=2.06M,符合預期。
3.3 Top Consumers
分析應用中資源消耗最高的物件(Biggest Object)、類(Biggest Top-Level Dominator Classes)、類載入器(Biggest Top-Level Dominator Class Loaders)及包(Biggest Top-Level Dominator Packages)。
除了包之外,上面三個統計都有一個餅圖展示結合一個表格展示。比如展開物件的統計資訊如下圖所示,同Dominator Tree中統計資訊相同。
3.4 Duplicate Classes
發現被不同類載入器重複載入的類,如下圖所示,發現都是Lambda相關的,無應用中的類,符合預期。
4 Report
4.1 Leak Suspects
幫助分析應用記憶體洩漏的工具,結合了餅圖與問題列表的形式展示分析結果,可以直接點選問題的Details跳轉到具體的問題中進行分析。
本應用懷疑有三個地方有記憶體洩漏,第一個和第三個是類載入器及執行緒組
點選第二個problem 的detail 進行檢視,可以看到問題詳情頁中包含五個部分:
1.Description(問題描述)
一個名為SynMap被WebAppClassLoader載入的物件共佔用了2162040 bytes(佔當前已使用記憶體的10%)。記憶體累積在 載入器載入的HashMap$Node例項中。
2.Shortest Paths To the Accumulation Point(問題物件到GC根節點的最短路徑)
當前分析出來的問題物件HashMap是用來儲存黑白名單快取的物件,可以看到導GC根節點時經過了SynMap,最終被多個Thread使用。所以此處可以排除非應用中的記憶體洩漏。
3.Accumulated Objects in Dominator Tree(以當前問題物件為根的Dominator支配樹)
此處列出了HashMap的支配樹,可以發現它是被SynMap引用且包含了一個大小為16384的陣列,點選下圖紅線的節點,從左邊的Attributes中可以檢視其具體的屬性。
4.Accumulated Objects by Class in Dominator Tree(以當前問題物件為根的Dominator支配樹按類的維度分類統計)
這裡其實是將上面的支配樹中的物件按類彙總了一下,檢視相關類佔用的記憶體大小。
5.All Accumulated Objects by Class(所有物件按類的維度統計佔用記憶體分析)
這裡不同上面的支配樹中的類統計,是將所有該物件中使用到的類進行了彙總統計。發現Char[]佔用了最大,其次是Date物件,這裡我們只觀察下大小即可。
4.2 Top Components
展示了大於1%記憶體的元件
沒有發現跟應用相關的類,我們可以點選第一個進行檢視具體的分析。
該詳情頁面有包含可能的記憶體浪費分析的,如下圖顯示有重複字串分析、空集合分析及集合填充率分析等。本應用沒有出現過度使用的空集合及大量低填充率的集合,但是發現有重複字串的問題。
可以看到問題描述為找到了119個char[]例項,其中至少有10個例項具有相同的內容,總大小為2609832bytes。什麼意思呢,就是重複出現最少十次的char[]共有119個,點選Detail進行檢視具體重複字串資訊。
這裡可以看到所有的重複char[],如果想看具體的重複資訊,選擇Histogram中具體的字串的連結檢視。比如我們點選第二個字串的連結檢視,發現字串中儲存的都是我們介面的返回值資訊。其他的重複字串統計也基本是由於壓測時大量建立物件造成,這裡沒什麼我們應用內部的問題,可以繼續分析其他指標。
(本節詳細分析TODO)也有物件軟弱引用及實現了finalize方法、map集合碰撞率等的分析。關於soft 和 weak 引用我們大致看一下就OK了,沒什麼問題就可以,詳細的統計可以點選Detail檢視。
軟引用統計:這裡有一共2874個軟引用物件。共有21310個物件一共971。9kb被軟引用保留在記憶體中。
弱引用統計:一共有8905個弱引用物件。共有90個物件一共4。2kb被弱引用保留在記憶體中。
Finalizer 統計:共有409個物件實現了finalize方法。
Map碰撞率分析:檢測到一個HashMap物件的碰撞率超過了80%。點選Detail可以檢視應用中各個集合的碰撞率,我們點開HashMap,如下圖缺失發現了一個物件的碰撞率超過80%,這正是上述統計的那個佔用了344byte的Map。
我們想看下這個Map裡儲存的是什麼,點選表中<=0.8的藍色連結。點選List objects -> with outgoing references可以檢視當前的HashMap中儲存的是什麼。如下圖所示,HashMap中儲存的為一些TcpEndpoint的物件資訊。