在Java基礎(chǔ):java虛擬機(jī)(JVM)中锰茉,我們提到了Java的四種引用。包括:強(qiáng)引用切心,軟引用飒筑,弱引用片吊,虛引用。這篇博客將詳細(xì)的講解一下這四種引用协屡。
1. 強(qiáng)引用
默認(rèn)的Object object=new Object()
的形式中,object即是對(duì)象new Object()的強(qiáng)引用俏脊,只有在object這個(gè)引用被釋放后,對(duì)象才會(huì)被釋放掉肤晓。這也是我們最常用的編碼方式爷贫。如果一個(gè)引用是強(qiáng)引用,即使內(nèi)存不足补憾,GC也絕對(duì)不會(huì)回收它漫萄,而是寧可拋出OutOfMemoryError錯(cuò)誤。
2. 軟引用
如果一個(gè)對(duì)象僅有軟引用盈匾,那么當(dāng)內(nèi)存充足時(shí)腾务,GC不會(huì)回收它,當(dāng)內(nèi)存不足時(shí)削饵,GC會(huì)對(duì)其回收岩瘦。此時(shí),需要通過sf.get()方法可以取到這個(gè)對(duì)象窿撬,當(dāng)然启昧,當(dāng)這個(gè)對(duì)象被標(biāo)記為需要回收的對(duì)象時(shí),則返回null劈伴;
軟引用主要用戶實(shí)現(xiàn)類似緩存的功能密末,在內(nèi)存足夠的情況下直接通過軟引用取值,無需從繁忙的真實(shí)來源查詢數(shù)據(jù)跛璧,提升速度苏遥;當(dāng)內(nèi)存不足時(shí),自動(dòng)刪除這部分緩存數(shù)據(jù)赡模,從真正的來源查詢這些數(shù)據(jù)田炭。
通常情況下,軟引用可以和一個(gè)引用隊(duì)列共同使用漓柑。即當(dāng)軟引用的對(duì)象被GC回收后教硫,JVM把這個(gè)軟引用加入與之關(guān)聯(lián)的隊(duì)列中。軟引用實(shí)例如下:
ReferenceQueue referenceQueue=new ReferenceQueue();
SoftReference<Integer> softReference=new SoftReference<Integer>(new Integer(3),referenceQueue);
System.out.println("softReference.get(): "+softReference.get());//通過此方法獲取軟引用對(duì)象辆布,可能會(huì)失敗
System.out.println("softReference.isEnqueued(): "+softReference.isEnqueued());//返回是否被標(biāo)記為即將回收的垃圾
運(yùn)行結(jié)果如下
softReference.get(): 3
softReference.isEnqueued(): false
3. 弱引用
弱引用相較于軟引用有更短的生命周期瞬矩,一旦GC發(fā)現(xiàn)只具有弱引用的對(duì)象,無論當(dāng)前內(nèi)存是否不足锋玲,都會(huì)對(duì)其進(jìn)行回收景用。GC是一個(gè)優(yōu)先級(jí)(優(yōu)先級(jí)的內(nèi)容可以參考Java多線程:生命周期,實(shí)現(xiàn)與調(diào)度中3.4節(jié):線程的優(yōu)先級(jí))很低的線程,不一定很快發(fā)現(xiàn)只具有弱引用的對(duì)象伞插。弱引用的使用方法和軟引用類似:
WeakReference<Integer> weakReference=new WeakReference<Integer>(new Integer(4),referenceQueue);
System.out.println("weakReference.get(): "+weakReference.get());//通過此方法獲取軟引用對(duì)象割粮,可能會(huì)失敗
System.out.println("weakReference.isEnqueued(): "+weakReference.isEnqueued());//返回是否被標(biāo)記為即將回收的垃圾
運(yùn)行結(jié)果如下,可以看出媚污,GC并不會(huì)立即執(zhí)行舀瓢。
weakReference.get(): 4
weakReference.isEnqueued(): false
弱引用主要用于監(jiān)控對(duì)象是否被標(biāo)記為即將被回收的垃圾。與軟引用類似耗美,弱引用也可以和引用隊(duì)列共同使用京髓。
4. 虛引用
虛引用又稱幽靈引用,不會(huì)決定對(duì)象的生命周期商架。如果一個(gè)對(duì)象僅存在一個(gè)虛引用堰怨,那么就和沒有引用相同,任何時(shí)候都可能被GC回收蛇摸。虛引用主要用于跟蹤GC的活動(dòng)诚些。虛引用必須和引用隊(duì)列聯(lián)合使用,GC回收一個(gè)對(duì)象時(shí)如果發(fā)現(xiàn)有其虛引用就會(huì)先把虛引用置于引用隊(duì)列中皇型。
PhantomReference phantomReference = new PhantomReference (new Integer(5), referenceQueue);
System.out.println("phantomReference.get(): "+phantomReference.get());//通過此方法獲取軟引用對(duì)象,可能會(huì)失敗
System.out.println("phantomReference.isEnqueued(): "+phantomReference.isEnqueued());//返回是否被標(biāo)記為即將回收的垃圾
運(yùn)行結(jié)果如下砸烦,可見弃鸦,虛引用會(huì)立刻被GC回收,相當(dāng)于沒有引用幢痘。
phantomReference.get(): null
phantomReference.isEnqueued(): false