前言
快速定位性能故障并非一朝一夕之功,需要我們對很多概念有很深刻的理解担汤,在前文中,我們介紹了heap dump的相關概念和其獲取方式选浑,今天我們一起來了解一下什么是:
Shallow 和 retained sizes杖玲。
GC ROOT是什么顿仇?
在java語言中,都是通過可達性分析來判定對象是否存活的摆马。此算法的基本思路是:通過一系列的稱為“GC Roots”的對象作為起點臼闻,從這些節(jié)點向下搜索,搜索所走過的路徑稱為引用鏈(Reference Chain)囤采,當一個對象到GC Roots沒有任何引用鏈相連述呐,則證明此對象是不可達的。
在上圖右側中蕉毯,我們可以看到乓搬,對象5/6/7雖然有依賴關聯(lián)思犁,但是他們到GC ROOT根節(jié)點是不可達的,所以這三個節(jié)點對象會被判定為是可回收的进肯。
GC ROOT的定義比較特別抒倚,他們不屬歸屬于對象圖中,對象也不能反向的依賴他們坷澡,這也確保了不會出現(xiàn)循環(huán)引用的問題托呕。因此也容易得出,只有引用類型的變量才被認為是Roots频敛,值類型的變量永遠不被認為是Roots项郊。
在Java中,可作為GC Roots的對象包括以下幾種:
虛擬機棧(棧幀中的局部變量表斟赚,Local Variable Table)中引用的對象着降。
方法區(qū)中類靜態(tài)屬性引用的對象。
方法區(qū)中常量引用的對象拗军。
本地方法棧中JNI(即一般說的Native方法)引用的對象任洞。
看到這里你可能要問,選擇這些對象的依據(jù)是什么呢发侵?
首先交掏,GCROOT的目標對象是要以當前還在存活的對象集合,因此必須要選取確定存活的引用類型對象刃鳄,GC管理的區(qū)域是java的堆盅弛,虛擬機棧、方法區(qū)和本地方法棧不被GC所管理叔锐,因此選用這些區(qū)域內引用的對象作為GC Roots挪鹏,是不會被GC回收的。
其中虛擬機棧和本地方法棧都是線程私有的內存區(qū)域愉烙,只要線程沒有終止讨盒,就能確保它們中引用的對象的存活。而方法區(qū)中類靜態(tài)屬性引用的對象是顯然存活的步责。常量引用的對象在當前可能存活返顺,因此,也可能是GC roots的一部分勺择。
下圖是使用MAT工具中的 “path to GC roots ”功能分析出來的引用鏈创南。
它標識從當前對象到GC roots的路徑,這個路徑解釋了為什么當前對象還能存活省核,對分析內存泄露很有幫助稿辙。
在查詢到GC root的路徑時,默認是包含所有引用的气忠,從GC角度說邻储,一個對象無法被GC赋咽,一定是因為有強引用存在,其它引用類型在GC需要的情況下都是可以被GC掉的吨娜,所以這里我使用 exclude all phantom/weak/soft etc. references 只查看GC路徑上的強引用脓匿。
shallow heap和retained heap
直譯過來是淺層堆和保留堆的意思。先說一說其基本的概念宦赠。
shallow heap
表示對象本身占用內存的大小陪毡,也就是對象頭加成員變量(不是成員變量的值)的總和。
如一個引用占用32或64bit勾扭,一個integer占4bytes毡琉,Long占8bytes等。
如簡單的一個類里面只有一個成員變量int i妙色,那么這個類的shallow size是12字節(jié)桅滋,因為對象頭是8字節(jié),成員變量int是4字節(jié)身辨。
常規(guī)對象(非數(shù)組)的Shallow size有其成員變量的數(shù)量和類型決定丐谋,數(shù)組的shallow size有數(shù)組元素的類型(對象類型、基本類型)和數(shù)組長度決定煌珊。
對象的值是分配給存儲對象本身的內存量号俐,不考慮所引用的對象。常規(guī)(非數(shù)組)對象的淺大小取決于其字段的數(shù)量和類型怪瓶。數(shù)組的淺尺寸取決于數(shù)組的長度及其元素(對象萧落、基本類型)的類型践美。一組對象的淺尺寸表示該集合中所有對象的淺尺寸之和洗贰。
retained heap
如果一個對象被釋放掉,那會因為該對象的釋放而減少引用進而被釋放的所有的對象(包括被遞歸釋放的)所占用的heap大小陨倡,即對象被垃圾回收器回收后能被GC從內存中移除的所有對象之和敛滋。相對于shallow heap,Retained heap可以更精確的反映一個對象實際占用的大行烁铩(若該對象釋放绎晃,retained heap都可以被釋放)。
實際案例分析
正如上圖所示:
在這兩張圖中杂曲,我們畫出了GC ROOT到所有對象引用鏈。在這里我們著重分析一下Retained size。
對于obj1這個對象:
GC ROOT指向它封寞,并且它依賴于obj2刀崖、obj3、obj4棚饵,但是由于obj3同樣也被GC ROOT所指煤裙。
所以:
分析obj1:
對于圖1掩完,retained size包括:obj1+obj2+obj4
對于圖2,retained size包括:obj1+obj2+obj3+obj4
分析obj2:
對于圖1:retained size包括:obj2+obj4
對于圖2:retained size包括:obj2+obj3+obj4
總結
本篇文章圍繞內存分析中的Shallow 和Retained heap擴展了解了幾個知識點如下:
- gc root的定義和概念的了解硼砰。
- 對象可達性分析和選擇gc root的依據(jù)且蓬。
- 針對單個對象使用“path to GC roots”查看其引用樹。
- shallow heap和retained heap的基本概念题翰。