淺談兩個相互引用的對象是否會被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:自學編程 |