一、前言
忘記之前是怎么接觸到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,小杜比亞-博客園