Java的虛擬機本身是蠻複雜的,我們不仔細講細節。我們只針對我們平時最關心的堆中的哪些對象會被GC回收。我們這樣思考,既然GC要回收這塊內存,那總得有個方法讓GC可以判斷哪些對象時可以被回收而哪些是不能被回收的吧?這就引出了下面常見的兩種判斷方法。
引用計數法
可達性分析算法
下面便具體講解下兩種方法:
. 引用計數法
這種方法是在對象的頭處維護一個計數器Counter,當有一個引用指向對象的時候counter就加一,當不在引用此對象時就讓counter減一。所以,當counter等於零的時候虛擬機就認爲此對象時可以被回收的。看起來好像有點道理,但是這種方法存在一個致命的問題:
如上圖所示:外部對對象A有一個引用,對象A持有對象B,而對象B也持有一個對象C,對象C又持有對象A。如果對於對象A的引用r失效,按照引用計數方法,GC永遠無法回收上面的三個對象。所以基於上面的存在內存泄漏的巨大缺陷,Java虛擬機(應該是大多數虛擬機)不採用此方法進行回收內存。
. 可達性分析算法
Java就是使用此方法作爲判斷對象是否可被回收的。虛擬機會先將一些對象定義爲GC Roots,從GC Roots出發一直沿着引用鏈向下尋找,如果某個對象不能通過GC Roots尋找到,那麼虛擬機就認爲該對象可以被回收。我們舉個例子,如下圖:
當對象D不在引用對象A時,儘管A、B、C互相還持有引用,GC依然會回收ABC所佔用的內存。那麼還有個疑問,什麼樣的對象可以被看做是GC Roots呢?
虛擬機棧(棧楨中的本地變量表)中的引用的對象
方法區中的類靜態屬性引用的對象
方法區中的常量引用的對象
本地方法棧中JNI(Native方法)的引用的對象
怎麼樣,看完本篇感覺對你有一點點的幫助麻煩關注????????????的公衆號哦~
《Effective Java》、《編程之美》等書籍免費送活動正在進行中哦~歡迎關注公衆號,點擊公衆號菜單的左下方領取福利哦~