1)引用出現的根源
引用出現的根源是由於GC內存回收的基本原理。GC回收本質上是回收對象。目前比較流行的回收算法是可達性分析算法。從GC roots開始安裝一定的邏輯判斷一個對象是否可達,不可達的話就說明這個對象已死。(除此之外另外一種常見的算法是引用計數法,但是這種算法有個問題就是不能解決相互引用的問題)。
基於此Java向用戶提供了四種可用的引用(強引用、軟引用、弱引用、幻象引用),同時還提供了一種不可被使用的引用(FinalReference)這個引用是和析構函數相關的。
2)四種引用的概念,特點,使用場景及區別
①強引用
我們平常典型代碼Object obj=new Object()中的obj就是強引用。通過關鍵字new創建的對象所關聯的引用就是強引用。當JVM內存空間不足,JVM寧願拋出OutOfMemoryError運行時錯誤(OOM),使程序異常終止,也不會隨意回收具有強引用的“存活”對象來解決內存不足的問題。對於一個普通的對象,如果沒有其他的引用關系,只要超過了引用的作用域或者顯示的將相應引用賦值為null,就是可以被垃圾收集了,具體回收時機還是要看垃圾收集策略。
應用場景:項目中到處都在使用
②軟引用
軟引用通過SoftReference類來實現。軟引用的生命周期比強引用短一些。只有當JVM認為內存不足時,才會去試圖回收軟引用指向的對象:即JVM會確保在拋出OutOfMemoryError之前,清理軟引用指向的對象。軟引用可以和引用隊列(ReferenceQueue)聯合使用,如果軟引用所引用的對象被垃圾回收器回收,Java虛擬機就會把這個軟引用加入到與之關聯的引用隊列中。后續我們可以調用ReferenceQueue的poll()方法來檢查是否有它所關心的對象被回收。如果隊列為空,將返回一個null,否則該方法返回隊列中前面的一個Reference對象。
應用場景:軟引用通常用來實現內存敏感的緩存。如果還有空閑內存,就可以暫時保留緩存,當內存不足時可以清理掉,這樣就保證了使用緩存的同時,不會耗盡內存。
③弱引用
弱引用通過WeakReference類來實現。弱引用的生命周期比軟引用短。在垃圾回收器線程掃描它所管轄的內存區域的過程中,一旦發現了具有弱引用的對象,不管當前內存空間足夠與否,都會回收它的內存。由於垃圾回收器是一個優先級很低的線程,因此不一定會很快回收弱引用的對象。弱引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果弱引用所引用的對象被垃圾回收,Java虛擬機就會把這個弱引用加入到與之關聯的引用隊列中。
應用場景: 弱引用同樣可用於內存敏感的緩存。
④幻象引用
幻象引用也叫虛引用,通過PhantomReference類來實現。無法通過虛引用訪問對象的屬性或函數。幻象引用僅僅是提供了一種確保對象被finalize之后,做某些事情的機制。如果一個對象僅持有虛引用,那么它和沒有任何引用一樣。在任何時候都可能被垃圾回收器回收。虛引用必須和引用隊列(ReferenceQueue)聯合使用。 當垃圾回收器准備回收一個對象時,如果發現它還有虛引用,就會在回收對象的內存之前,把這個虛引用加入到與之關聯的引用隊列中。
ReferenceQueue queue=new ReferenceQueue();
PhantomReference pr=new PhantomReference(object,queue);
程序可以通過判斷引用隊列中是否已經加入了虛引用,來了解被引用的對象是否將要被垃圾回收。如果程序發現某個虛引用已經被加入到引用對列,那么就可以在所引用的對象的內存被回收之前采取一些程序行動。
應用場景: 可用來跟蹤對象被垃圾回收器回收的活動,當一個虛引用關聯的對象被垃圾收集齊回收之前收到一個系統通知。
3)擴展
這是一個評論者提供的一篇文章,讀讀它去理解這幾個reference的概念和作用,很有幫助
http://www.kdgregory.com/index.php?page=java.refobj
