Java中的四種引用型別(強、軟、弱、虛)
為什麼需要不同的引用型別
從Java1.2開始,JVM開發團隊發現,單一的強引用型別,無法很好的管理物件在JVM裡面的生命週期,垃圾回收策略過於簡單,無法適用絕大多數場景。為了更好的管理物件的記憶體,更好的進行垃圾回收,JVM團隊擴充套件了引用型別,從最早的強引用型別增加到強、軟、弱、虛四個引用型別。
引用類圖
引用類圖
StrongRerence為JVM內部實現。其他三類引用型別全部繼承自Reference父類。
強引用(StrongReference)
最常用到的引用型別,StrongRerence這個類並不存在,而是在JVM底層實現。預設的物件都是強引用型別,繼承自Rerence、SoftReference、WeakReference、PhantomReference的引用型別非強引用。
最簡單的強引用示例:
String str = "Misout的部落格";
強引用型別,如果JVM垃圾回收器GC Roots可達性分析結果為可達,表示引用型別仍然被引用著,這類物件始終不會被垃圾回收器回收,即使JVM發生OOM也不會回收。而如果GC Roots的可達性分析結果為不可達,那麼在GC時會被回收。
軟引用(SoftReference)
軟引用是一種比強引用生命週期稍弱的一種引用型別。在JVM記憶體充足的情況下,軟引用並不會被垃圾回收器回收,只有在JVM記憶體不足的情況下,才會被垃圾回收器回收。所以軟引用的這種特性,一般用來實現一些記憶體敏感的快取,只要記憶體空間足夠,物件就會保持不被回收掉,比如網頁快取、圖片快取等。
軟引用使用示例
SoftReference<String> softReference = new SoftReference<String>(new String("Misout的部落格"));
System.out.println(softReference.get());
弱引用(WeakReference)
弱引用是一種比軟引用生命週期更短的引用。他的生命週期很短,不論當前記憶體是否充足,都只能存活到下一次垃圾收集之前。
來讓我們看一個示例
WeakReference<String> weakReference = new WeakReference<String>(new String("Misout的部落格")); System.gc(); if(weakReference.get() == null) { System.out.println("weakReference已經被GC回收"); }
輸出結果:
weakReference已經被GC回收
從結果中能看出其存活的週期。
虛引用(PhantomReference)
虛引用與前面的幾種都不一樣,這種引用型別不會影響物件的生命週期,所持有的引用就跟沒持有一樣,隨時都能被GC回收。需要注意的是,在使用虛引用時,必須和引用佇列關聯使用。在物件的垃圾回收過程中,如果GC發現一個物件還存在虛引用,則會把這個虛引用加入到與之關聯的引用佇列中。程式可以通過判斷引用佇列中是否已經加入了虛引用,來了解被引用的物件是否將要被垃圾回收。如果程式發現某個虛引用已經被加入到引用佇列,那麼就可以在所引用的物件記憶體被回收之前採取必要的行動防止被回收。虛引用主要用來跟蹤物件被垃圾回收器回收的活動。
示例
PhantomReference<String> phantomReference = new PhantomReference<String>(new String("Misout的部落格"), new ReferenceQueue<String>());
System.out.println(phantomReference.get());
執行後,發現結果總是null,引用跟沒有持有差不多。
總結
型別 | 回收時間 | 使用場景 |
---|---|---|
強引用 | 一直存活,除非GC Roots不可達 | 所有程式的場景,基本物件,自定義物件等。 |
軟引用 | 記憶體不足時會被回收 | 一般用在對記憶體非常敏感的資源上,用作快取的場景比較多,例如:網頁快取、圖片快取 |
弱引用 | 只能存活到下一次GC前 | 生命週期很短的物件,例如ThreadLocal中的Key。 |
虛引用 | 隨時會被回收, 建立了可能很快就會被回收 | 業界暫無使用場景, 可能被JVM團隊內部用來跟蹤JVM的垃圾回收活動 |
以上這些引用可能對大部分人來說都不會用到,但不管怎樣,必須要了解以上四種引用型別的概念和區別,以及生存週期
作者:Misout
連結:https://www.jianshu.com/p/ca6cbc246d20
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。