標籤:產生 關係 帶來 虛引用 details return 判斷 query isp
一、前言
忘記之前是怎麼接觸到Java的強、軟、弱、虛引用的了,恍恍惚惚好像是在看記憶體回收的時候,略過了這些個概念~這些知識在平時開發中使用的真是少之又少(也許我的level還不夠)~今天就將這些整理完畢吧~
二、本文
對於Java中這幾種引用的理解,有助於理解JVM的回收記憶體的機制。先說下在JVM執行記憶體回收時,如何處理它們所引用的對象:
1)強引用,任何時候都不會被記憶體回收行程回收,如果記憶體不足,寧願拋出OutOfMemoryError。 2)軟引用,只有在記憶體將滿的時候才會被記憶體回收行程回收,如果還有可用記憶體,記憶體回收行程不會回收。 3)弱引用,只要記憶體回收行程運行,就肯定會被回收,不管還有沒有可用記憶體。 4)虛引用,虛引用等於沒有引用,任何時候都有可能被記憶體回收。
在JDK1.2之後,Java對引用的概念進行了擴充
下面就來介紹一下四種引用的概念:
強引用(Strong Reference):就是指在程式碼之中普遍存在的,類似Object obj = new Object();,這類的引用,只要強引用還存在,垃圾收集器寧願拋出OutOfMemory的錯誤,也不會回收被強引用所引用的對象
軟引用(Soft Reference):是用來描述一些還有用但並非必須的對象。對於軟引用關聯著的對象,在系統將要發生記憶體溢出異常之前,將會把這些對象列進回收範圍之中進行第二次回收。如果,這次回收沒有足夠的記憶體,才會拋出記憶體溢出異常,虛擬機器在拋出 OutOfMemoryError 之前會保證所有的軟引用(持有的對象)已被清除,此外,沒有任何約束保證軟引用(持有的對象)將在某個特定的時間點被清除,或者確定一組不同的軟引用(持有的對象)被清除的順序。不過,虛擬機器的具體實現會傾向於不清除最近建立或最近使用過的軟引用。在JDK1.2之後,提供了SoftReference類來實現軟引用。軟引用非常適合用來做快取,當系統記憶體不足的時候,緩衝中的內容是可以被釋放的:
import java.lang.ref.SoftReference;import java.util.HashMap;import java.util.Map;public class Test { private static Map<String, SoftReference> sqlCache = new HashMap<>(); private static Object getFromChache(String sql) { SoftReference sr = sqlCache.get(sql); Object object = sr == null ? null : sr.get(); if (object == null) { object = getFromQuery(sql); sqlCache.put(sql, new SoftReference(object)); } return object; } private static Object getFromQuery(String sql) { //從資料庫查詢,速度較慢。 if(條件){
............. return Object; } else{ return null; } }}
弱引用(Weak Reference):也是用來描述非必需對象的,但是它的強度比軟引用更弱一些,被弱引用關聯著的對象只能生存到下一次垃圾收集發生之前。當垃圾收集器工作時,無論當前記憶體是否足夠,都會回收掉只被引用關聯的對象。在JDK 1.2 之後,提供了WeakReference 類來實現弱引用。弱引用可以用到什麼地方呢,當你想引用一個對象,但是這個對象有自己的生命週期,你不想介入這個對象的生命週期,這時候你就是用弱引用。這個引用不會在對象的記憶體回收判斷中產生任何附加的影響(這個可以從後文“對象可達性”內容部分得到答案)。
虛引用(Phantom Reference):也稱為幽靈引用或者幻影引用,它是最弱的一種參考關聯性。一個對象是否有虛引用的存在,完全不會對其生命週期構成影響,也無法通過虛引用來取得一個對象執行個體。為一個對象設定虛引用關聯的唯一目的就是能在這個對象被收集器回收時收到一個系統通知。在JDK1.2之後,提供了PhantomReference類來實現虛引用。虛引用與軟引用和弱引用的一個區別在於:虛引用必須和引用隊列(ReferenceQueue)聯合使用。當記憶體回收行程準備回收一個對象時,如果發現它還有虛引用,就會在回收對象的記憶體之前,把這個虛引用加入到與之關聯的引用隊列中。程式可以通過判斷引用隊列中是否已經加入了虛引用,來瞭解。
接下來介紹一下,在記憶體回收中,對象的可達性判斷:
在記憶體回收中,一般是對某些引用(比如軟、弱、虛引用)或者不可達對象進行記憶體回收,在判斷一個對象是否可達的時候,先從根集(Object對象)開始尋找,如果沒有路徑到達某個對象,那麼這個對象就是“不可達”對象,會在記憶體回收的時候被回收。如果有路徑可達的情況下,那麼就需要判斷這個“可達”的強弱程度。
如所示,在這個樹形的引用鏈中,箭頭的方向代表了引用的方向,所指向的對象是被引用對象。由圖可以看出,從根集到一個對象可以由很多條路徑。比如到達對象5的路徑就有①-⑤,③-⑦兩條路徑。由此帶來了一個問題,那就是某個對象的可達性如何判斷:
◆單條引用路徑可達性判斷:在這條路徑中,最弱的一個引用決定對象的可達性
◆多條引用路徑可達性判斷:幾條路徑中,最強的一條的引用決定對象的可達性
比如,我們假設圖中引用①和③為強引用,⑤為軟引用,⑦為弱引用,對於對象5按照這兩個判斷原則,路徑①-⑤取最弱的引用⑤,因此該路徑對對象5的引用為軟引用。同樣,③-⑦為弱引用。在這兩條路徑之間取最強的引用,於是對象5是一個軟可達對象。
三、連結
http://www.cnblogs.com/yw-ah/p/5830458.html
https://my.oschina.net/ydsakyclguozi/blog/404389
http://developer.51cto.com/art/200906/128189.htm
http://blog.csdn.net/luoyanglizi/article/details/51137704
http://blog.csdn.net/zhuojianhai88/article/details/13503007
http://blog.csdn.net/moxuelang/article/details/50762253
http://blog.csdn.net/lyfi01/article/details/6415726
四、聯絡本人
為方便沒有部落格園帳號的讀者交流,特意建立一個企鵝群(純公益,非利益相關),讀者如果有對博文不明之處,歡迎加群交流:261746360,小杜比亞-部落格園
Java中強、軟、弱、虛引用