Java中的四種引用類型(強(qiáng)、軟、弱、虛)
從Java1.2開始,JVM開發(fā)團(tuán)隊(duì)發(fā)現(xiàn),單一的強(qiáng)引用類型,無(wú)法很好的管理對(duì)象在JVM里面的生命周期,垃圾回收策略過(guò)于簡(jiǎn)單,無(wú)法適用絕大多數(shù)場(chǎng)景。為了更好的管理對(duì)象的內(nèi)存,更好的進(jìn)行垃圾回收,JVM團(tuán)隊(duì)擴(kuò)展了引用類型,從最早的強(qiáng)引用類型增加到強(qiáng)、軟、弱、虛四個(gè)引用類型。
引用類圖
StrongRerence為JVM內(nèi)部實(shí)現(xiàn)。其他三類引用類型全部繼承自Reference父類。
強(qiáng)引用(StrongReference)
最常用到的引用類型,StrongRerence這個(gè)類并不存在,而是在JVM底層實(shí)現(xiàn)。默認(rèn)的對(duì)象都是強(qiáng)引用類型,繼承自Rerence、SoftReference、WeakReference、PhantomReference的引用類型非強(qiáng)引用。
最簡(jiǎn)單的強(qiáng)引用示例:
String str = "hello";
強(qiáng)引用類型,如果JVM垃圾回收器GC Roots可達(dá)性分析結(jié)果為可達(dá),表示引用類型仍然被引用著,這類對(duì)象始終不會(huì)被垃圾回收器回收,即使JVM發(fā)生OOM也不會(huì)回收。而如果GC Roots的可達(dá)性分析結(jié)果為不可達(dá),那么在GC時(shí)會(huì)被回收。
軟引用(SoftReference)
軟引用是一種比強(qiáng)引用生命周期稍弱的一種引用類型。在JVM內(nèi)存充足的情況下,軟引用并不會(huì)被垃圾回收器回收,只有在JVM內(nèi)存不足的情況下,才會(huì)被垃圾回收器回收。所以軟引用的這種特性,一般用來(lái)實(shí)現(xiàn)一些內(nèi)存敏感的緩存,只要內(nèi)存空間足夠,對(duì)象就會(huì)保持不被回收掉,比如網(wǎng)頁(yè)緩存、圖片緩存等。
軟引用示例
SoftReference<String> softReference = new SoftReference<String>(new String("Misout的博客"));
System.out.println(softReference.get());
弱引用(WeakReference)
弱引用是一種比軟引用生命周期更短的引用。他的生命周期很短,不論當(dāng)前內(nèi)存是否充足,都只能存活到下一次垃圾收集之前。
來(lái)讓我們看一個(gè)示例
WeakReference<String> weakReference = new WeakReference<String>(new String("Misout的博客"));
System.gc();
if(weakReference.get() == null) {
System.out.println("weakReference已經(jīng)被GC回收");
}
虛引用(PhantomReference)
虛引用與前面的幾種都不一樣,這種引用類型不會(huì)影響對(duì)象的生命周期,所持有的引用就跟沒(méi)持有一樣,隨時(shí)都能被GC回收。需要注意的是,在使用虛引用時(shí),必須和引用隊(duì)列關(guān)聯(lián)使用。在對(duì)象的垃圾回收過(guò)程中,如果GC發(fā)現(xiàn)一個(gè)對(duì)象還存在虛引用,則會(huì)把這個(gè)虛引用加入到與之關(guān)聯(lián)的引用隊(duì)列中。程序可以通過(guò)判斷引用隊(duì)列中是否已經(jīng)加入了虛引用,來(lái)了解被引用的對(duì)象是否將要被垃圾回收。如果程序發(fā)現(xiàn)某個(gè)虛引用已經(jīng)被加入到引用隊(duì)列,那么就可以在所引用的對(duì)象內(nèi)存被回收之前采取必要的行動(dòng)防止被回收。虛引用主要用來(lái)跟蹤對(duì)象被垃圾回收器回收的活動(dòng)。
示例
PhantomReference<String> phantomReference = new PhantomReference<String>(new String("Misout的博客"), new ReferenceQueue<String>());
System.out.println(phantomReference.get());
運(yùn)行后,發(fā)現(xiàn)結(jié)果總是null,引用跟沒(méi)有持有差不多。
總結(jié)
類型 | 回收時(shí)間 | 使用場(chǎng)景 |
---|---|---|
強(qiáng)引用 | 一直存活,除非GC Roots不可達(dá) | 所有程序的場(chǎng)景,基本對(duì)象,自定義對(duì)象等 |
軟引用 | 內(nèi)存不足時(shí)會(huì)被回收 | 一般用在對(duì)內(nèi)存非常敏感的資源上,用作緩存的場(chǎng)景比較多,例如:網(wǎng)頁(yè)緩存、圖片緩存 |
弱引用 | 只能存活到下一次GC前 | 生命周期很短的對(duì)象,例如ThreadLocal中的Key。 |
虛引用 | 隨時(shí)會(huì)被回收, 創(chuàng)建了可能很快就會(huì)被回收 | 業(yè)界暫無(wú)使用場(chǎng)景, 可能被JVM團(tuán)隊(duì)內(nèi)部用來(lái)跟蹤JVM的垃圾回收活動(dòng) |