標籤:

淺談兩個相互引用的對象是否會被GC回收

兩個相互引用的對象會被GC垃圾回收嗎?答案應該是不會!只要對象、屬性等存在被引用,GC都會過濾掉的,不會被回收。筆者就簡單談一談其中的原理吧。

判斷對象是否存活,可以考慮以下方法。

1、引用計數演算法

給對象添加一個引用計數器,每當有一個地方引用它時,計數器值就加1。

當引用失效時,計數器值就減1。

任何時刻計數器為0的對象就是不可能再被使用的。

但是主流的java虛擬機沒有採用引用計數演算法,其中最主要的原因就是它很難解決對象之間互相循環引用的問題。

例子:

對象A和B互相引用,但除此之外,這兩個對象再無任何引用,但是他們因為互相引用著對方,所以導致他們的引用計數都不為0,於是引用計數演算法無法通知GC收集器回收他們。

(代碼示例解釋什麼是循環引用)

class A { public B bb;}class B { public A aa;}public class TestGC { public static void main(String[] args) { A a = new A(); B b = new B(); a.bb = b; b.aa = a; a = null; b = null; }}

在上面的代碼示例中,假設我們有兩個類分別是A和B,A類中有一個欄位是B類的類型,B類中有一個欄位是A類類型,現在分別new一個A類對象和new一個B類對象,此時引用a指向剛new出來的A類對象,引用b指向剛new出來的B類對象,然後將兩個類中的欄位互相引用一下,這樣即使下面進行a = null和b = null,但是A類對象仍然被B類對象中的欄位引用著,儘管現在A類和B類獨享都已經訪問不到了,但是引用計數卻都不為0.

2、可達性分析演算法(主流演算法)

主流的實現中,都是通過可達性分析來判定對象是否存活。

演算法的基本思想:通過一系列的被稱為「gc roots」的對象作為起始點,從這些節點開始向下搜索,搜索所走過的路徑稱為引用鏈,當一個對象到「gc roots」沒有任何引用鏈相連時,則證明此對象是不可用的。

可以作為「gc roots」的對象

(1)虛擬機棧(棧針中的局部變數表)中引用的對象

(2)方法區中類靜態屬性引用的對象。

(3)方法區中常量引用的對象

(4)本地方法棧中JNI引用的對象。

以上就是兩個驗證兩個相互引用的對象是否會被GC垃圾回收的方法,希望對正在編程道路上努力的同學們有所幫助!


推薦閱讀:

工廠模式、工廠方法模式和抽象工廠模式的差異分析
簡析組件AWT和Swing各有的優缺點及區別

TAG:自學編程 |