Java四種引用類型java
1.引用的基本概念面試
強引用:當咱們使用new建立對象時,被建立的對象就是強引用,如Object object = new Object(),其中的object就是一個強引用了。若是一個對象具備強引用,JVM就不會去GC它,JVM寧肯會報OOM來終止程序,也不回收該對象。編程
軟引用: 若是一個對象只具有軟引用,若是內存空間足夠,那麼JVM就不會GC它,若是內存空間不足了,就會GC該對象。緩存
弱引用: 若是一個對象只具備弱引用,只要JVM的GC線程檢測到了,就會當即回收。弱引用的生命週期要比軟引用短不少。不過,若是垃圾回收器是一個優先級很低的線程,也不必定會很快就會釋放掉軟引用的內存。spa
虛引用:若是一個對象只具備虛引用,那麼它就和沒有任何引用同樣,隨時會被JVM看成垃圾進行GC。線程
上面的四種引用對應的是new關鍵字以及java.lang.ref包中的SoftReference,WeakReference, PhantomReference。咱們注意到在java.lang.ref包中,還存在一個類叫作ReferenceQueue。3d
在Java中提供了四個級別的引用:強引用,軟引用,弱引用和虛引用。在這四個引用類型中,只有強引用FinalReference類是包內可見,其餘三種引用類型均爲public,能夠在應用程序中直接使用。引用類型的類結構如圖所示。指針
平時咱們編程的時候例如:Object object=new Object();那object就是一個強引用了。若是一個對象具備強引用,那就相似於必不可少的生活用品,垃圾回收器毫不會回收它。當內存空 間不足,Java虛擬機寧願拋出OutOfMemoryError錯誤,使程序異常終止,也不會靠隨意回收具備強引用的對象來解決內存不足問題。對象
Java中的引用,相似C語言中最難的指針。(我是C語言入門編程,指針的概念仍是很深刻我心。)經過引用,能夠對堆中的對象進行操做。如:blog
StringBuffer stringBuffer = new StringBuffer("Helloword");
變量str指向StringBuffer實例所在的堆空間,經過str能夠操做該對象。
強引用的特色:
若是一個對象只具備軟引用,那就相似於可有可物的生活用品。若是內存空間足夠,垃圾回收器就不會回收它,若是內存 空間不足了,就會回收這些對象的內存。只要垃圾回收器沒有回收它,該對象就能夠被程序使用。軟引用可用來實現內存敏感的高速緩存。 軟引用能夠和一個引用隊列(ReferenceQueue)聯合使用,若是軟引用所引用的對象被垃圾回收,Java虛擬機就會把這個軟引用加入到與之關聯 的引用隊列中。
軟引用是除了強引用外,最強的引用類型。能夠經過java.lang.ref.SoftReference使用軟引用。一個持有軟引用的對象,不會被JVM很快回收,JVM會根據當前堆的使用狀況來判斷什麼時候回收。當堆使用率臨近閾值時,纔會去回收軟引用的對象。所以,軟引用能夠用於實現對內存敏感的高速緩存。
SoftReference的特色是它的一個實例保存對一個Java對象的軟引用, 該軟引用的存在不妨礙垃圾收集線程對該Java對象的回收。也就是說,一旦SoftReference保存了對一個Java對象的軟引用後,在垃圾線程對 這個Java對象回收前,SoftReference類所提供的get()方法返回Java對象的強引用。一旦垃圾線程回收該Java對象以後,get()方法將返回null。
下面舉一個例子說明軟引用的使用方法。
在你的IDE設置參數-Xmx2m -Xms2m規定堆內存大小爲2m。
運行結果:
打開被註釋掉的new byte[1024*100]語句,這條語句請求一塊大的堆空間,使堆內存使用緊張。並顯式的再調用一次GC,結果以下:
說明在系統內存緊張的狀況下,軟引用被回收。
若是一個對象只具備弱引用,那就相似於可有可物的生活用品。弱引用與軟引用的區別在於:只具備弱引用的對象擁有更 短暫的生命週期。在垃圾回收器線程掃描它 所管轄的內存區域的過程當中,一旦發現了只具備弱引用的對象,無論當前內存空間足夠與否,都會回收它的內存。不過,因爲垃圾回收器是一個優先級很低的線程, 所以不必定會很快發現那些只具備弱引用的對象。 弱引用能夠和一個引用隊列(ReferenceQueue)聯合使用,若是弱引用所引用的對象被垃圾回收,Java虛擬機就會把這個弱引用加入到與之關聯 的引用隊列中。
弱引用是一種比軟引用較弱的引用類型。在系統GC時,只要發現弱引用,無論系統堆空間是否足夠,都會將對象進行回收。在java中,能夠用java.lang.ref.WeakReference實例來保存對一個Java對象的弱引用。
運行結果:
軟引用,弱引用都很是適合來保存那些無關緊要的緩存數據,若是這麼作,當系統內存不足時,這些緩存數據會被回收,不會致使內存溢出。而當內存資源充足時,這些緩存數據又能夠存在至關長的時間,從而起到加速系統的做用。
5、虛引用(PhantomReference):
「虛引用」顧名思義,就是形同虛設,與其餘幾種引用都不一樣,虛引用並不會決定對象的生命週期。若是一個對象 僅持有虛引用,那麼它就和沒有任何引用同樣,在任什麼時候候均可能被垃圾回收。 虛引用主要用來跟蹤對象被垃圾回收的活動。虛引用與軟引用和弱引用的一個區別在於:虛引用必須和引用隊列 (ReferenceQueue)聯合使用。當垃圾回收器準備回收一個對象時,若是發現它還有虛引用,就會在回收對象的內存以前,把這個虛引用加入到與之 關聯的引用隊列中。程序能夠經過判斷引用隊列中是否已經加入了虛引用,來了解被引用的對象是否將要被垃圾回收。程序若是發現某個虛引用已經被加入到引用隊 列,那麼就能夠在所引用的對象的內存被回收以前採起必要的行動。
在java.lang.ref包中提供了三個類:SoftReference類、WeakReference類和PhantomReference類,它們分別表明軟引用、弱引用和虛引用。ReferenceQueue類表示引用隊列,它能夠和這三種引用類聯合使用,以便跟蹤Java虛擬機回收所引用的對象的活動。
虛引用是全部類型中最弱的一個。一個持有虛引用的對象,和沒有引用幾乎是同樣的,隨時可能被垃圾回收器回收。當試圖經過虛引用的get()方法取得強引用時,老是會失敗。而且,虛引用必須和引用隊列一塊兒使用,它的做用在於跟蹤垃圾回收過程。
當垃圾回收器準備回收一個對象時,若是發現它還有虛引用,就會在垃圾回收後,銷燬這個對象,將這個虛引用加入引用隊列。程序能夠經過判斷引用隊列中是否已經加入了虛引用,來了解被引用的對象是否將要被垃圾回收。若是程序發現某個虛引用已經被加入到引用隊列,那麼就能夠在所引用的對象的內存被回收以前採起必要的行動。
運行結果:
對虛引用的get()操做,老是返回null,由於sf.get()方法的實現以下:
6、弱引用典例
WeakHashMap類在java.util包內,它實現了Map接口,是HashMap的一種實現,它使用弱引用做爲內部數據的存儲方案。WeakHashMap是弱引用的一種典型應用,它能夠做爲簡單的緩存表解決方案。
如下兩段代碼分別使用WeakHashMap和HashMap保存大量的數據:
使用-Xmx2M限定堆內存,使用WeakHashMap的代碼正常運行結束,而使用HashMap的代碼段拋出異常
因而可知,WeakHashMap會在系統內存緊張時使用弱引用,自動釋放掉持有弱引用的內存數據。
但若是WeakHashMap的key都在系統內持有強引用,那麼WeakHashMap就退化爲普通的HashMap,由於全部的表項都沒法被自動清理。