Java雜談2——引用與跟搜索算法

Java中的引用

  Java「引用」的概念源於C++,本來的定義至關有限:一個引用(Reference)表明的內存一般用於指向另外一塊內存區域的起始地址。經過引用類型保存的起始地址,能夠找到這個引用所指向的對象實例和在方法區中的對象類型數據。java

  區別於傳統的c/c++語言,Java的對象的銷燬徹底由垃圾回收器管理,核心問題就是什麼時候應該回收對象?c++

  Java的策略是:回收那些不再會被任何引用指向的對象,咱們將實例化對象的是否被引用的特性稱之爲可達性程序員

  其實,這種策略並不涵蓋全部的使用情景。試想,咱們但願建立一些緩存對象用於存儲臨時的中間計算結果,當內存充裕時將它們會保留在內存中;當內存很是緊張時,即便優先回收這些對象對程序的執行正確性並不會有影響。此時,傳統的Java引用就顯得一籌莫展了。自JDK1.2後,Java引用的概念獲得了新的擴展,將引用劃分爲強引用(Strong Reference)、軟引用(Soft Reference)、弱引用(Weak Reference)和虛引用(Phantom Reference)。算法

  強引用 > 軟引用 > 弱引用 > 虛引用緩存

  強引用:Java代碼中默認的引用類型就是強引用,除非實例化對象不可達,不然不會被回收。例子以下:函數

1 Object objRef = new Object(); //objRef是一個強引用

  軟引用:即便實例化對象可達,軟引用的對象仍是會發生內存溢出以前(Java堆內存不夠用時)被垃圾回收器回收,例子以下:spa

//上接以前的代碼,建立一個軟引用
SoftReference objSoftRef = new SoftReference(objRef);

Object objRef2 = (Object)objSoftRef.get(); //若是此時軟引用還未被回收,能夠經過這段代碼從新或獲得實例化對象的強引用,不然會返回null

 

  弱引用:比軟引用更弱,在下一次垃圾回收器收集到弱引用後對象會被回收,具體用法與軟引用一致,弱引用類類名爲WeakReference。code

  虛引用:這個引用很特殊,其存在不影響對應的實例化對象的生命週期,也不可以經過get方法再獲取到對象的強引用。與一個特殊的引用隊列(ReferenceQueue)配合使用能夠用於監聽實例化對象的回收事件。例子以下:對象

//上接以前代碼,建立一個引用隊列
/************************************************
** 解釋一下引用隊列:
** 在一個實例化對象被垃圾回收器回收以前,與這個對象相關的引用對象(Java.lang.refReference類型)都會被加入到與之相關的引用隊列中
*************************************************/
ReferenceQueue queue = new ReferenceQueue ();

//建立一個虛引用,同時將這個虛引用與隊列queue相關聯
PhantomReference objPhaRef = new PhantomReference(obj,queue);

assertNull(queue.poll());

obj = null;

//obj對象在被回收以前,objPhaRef 對象就會被加入到queue隊列中
assertNull(queue.poll());

 

 

 根搜索算法

  垃圾回收器在斷定一個對象是否能夠被回收時採用的是根搜索算法,基本思想:從已知的GC Roots對象開始遍歷向下搜索,找到全部的可達實例化對象,回收全部不可達的實例化對象。GC Roots對象包含以下:blog

  虛擬機棧中的引用對象

  方法區中的靜態引用對象

  常量池中的常量引用對象

  本地方法棧中的引用對象

 

  那麼,當一個實例化對象在被肯定不可達以後,會被立刻「殺死」嗎?

  答案是否認的,其中的例外小技巧就是在finalize()函數。爲了保證c++程序員可以接受,java提供了相似於析構函數的finalize,垃圾回收器保證一個對象在被真正銷燬以前一定調用過一次finalize。那麼,咱們就能夠在這個finalize函數中再次將本對象賦值給一個外部引用,試圖在真正銷燬以前挽救對象。(PS:可是須要注意的是,相似於表達finalize函數並非java中的虛構函數,它並不保證是在對象真正銷燬以前被調用的最後一個函數,它只保證一個對象在被銷燬以前一定會被調用過一次)。

相關文章
相關標籤/搜索