Java強引用,軟引用,弱引用與虛引用

參考資料深入理解

1 概述
引用類型 被回收時間 用途 生存時間
強引用 從來不會 對象的一般狀態 JVM停止運行時
軟引用 內存不足時 對象緩存 內存不足時
弱引用 JVM垃圾回收時 對象緩存 GC運行後
虛引用 未知 未知 未知
2 強引用(StrongReference)

開發中,定義的引用一般都是強引用,這是最普遍的使用。如果一個對象具有強引用,就是必不可少的對象,不會被垃圾回收器回收。
當內存空間不足時,JVM寧願拋出OOM異常,使程序終止,也不回收這種引用

// object和str 都是強引用
Object object = new Object();
String str = "123";

如果想中斷強引用和某個對象之間的關聯,可以顯示地將引用賦值爲 null,  這樣,JVM 會在合適的時間回收該對象。
ArrayList類的 clear()方法,就是通過將引用賦值爲 null,來實現清理工作的。

public void clear(){
    modCount++;
    // Let gc do its work
    for(int i=0; i<size;i++)
      elementData[i] = null;
    
    size = 0;
}

在ArrayList類中定義了一個私有的變量elementData數組,在調用方法清空數組時可以看到爲每個數組內容賦值爲null。不同於elementData=null,強引用仍然存在,避免在後續調用 add()等方法添加元素時進行重新的內存分配。使用如clear()方法中釋放內存的方法對數組中存放的引用類型特別適用,這樣就可以及時釋放內存。

3 軟引用(SoftReference)

軟引用,弱引用都可以和一個引用隊列(ReferenceQueue)聯合使用,虛引用必須和引用隊列聯合使用。在實際開發中,軟引用最常用,弱引用和虛引用很少使用

ReferenceQueue<String> queue = new ReferenceQueue<String>();
PhantomReference<String> pr = new  PhantomReference<String>(new String("hello"), queue);

軟引用是用來描述一些有用但不是必需的對象,在 Java中用 java.lang.ref.SoftReference類來表示。
對於軟引用關聯着的對象,只有在內存不足的時候,JVM纔會回收該對象。因此,這一點可以很好地用來解決OOM的問題,並且這個特性,很適合用來實現緩存:比如網頁緩存,圖片緩存等。

如何利用軟引用和弱引用解決OOM問題
假如有一個應用需要讀取大量的本地圖片。如果每次讀取圖片都從硬盤讀取,會嚴重影響性能;但是如果全部加載到內存中,有可能造成內存溢出。此時,使用軟引用可以解決這個問題。


設計思路
用一個 HashMap 來保存圖片的路徑 和 相應的圖片對象 關聯的軟引用 之間的映射關係。
當內存不足時,JVM 會自動回收這些緩存圖片對象,所佔用的空間,從而有效的避免了 OOM問題
在 Android開發中,對於大量圖片下載會經常用到

private Map<String, SoftReference<Bitmap>> imageCache = new
        HashMap<String,SoftReference<Bitmap>>();

public void addBitmapToCache(String path){
    // 強引用的 Bitmap對象
    Bitmap bitmap = BitmapFactory.decodeFile(path);
    // 軟引用的 Bitmap對象
    SoftReference<Bitmap> softBitmap = new SoftReference<Bitmap>(bitmap);
    //添加該對象到 Map中 使其緩存
    imageCache.put(path,softBitmap);
}

public Bitmap getBitmapByPath(String path){
    // 從緩存中 取軟引用的 Bitmap對象
    SoftReference<Bitmap> softBitmap = imageCache.get(path);
    // 判斷 是否存在軟引用
    if(softBitmap == null){
        return null;
    }
    // 取出 Bitmap對象,如果由於內存不足 Bitmap被回收,將取得空
    Bitmap bitmap = softBitmap.get();
    return bitmap;
}
4 弱引用(WeakReference)

弱引用也是用來描述非必需對象的,當JVM進行垃圾回收時,無論內存是否充足,都會回收被弱引用關聯的對象。在java中,用 java.lang.ref.WeakReference類來表示。
弱引用與軟引用的區別:被軟引用關聯的對象只有在內存不足時纔會被回收,而被弱引用關聯的對象在JVM進行垃圾回收時總會被回收

只具有弱引用的對象擁有更短暫的生命週期。在垃圾回收器線程掃描它所管轄的內存區域的過程中,一旦發現了只具有弱引用的對象,不管當前內存空間足夠與否,都會回收它的內存。不過,由於垃圾回收器是一個優先級很低的線程, 因此不一定會很快發現那些只具有弱引用的對象。

使用場景

如果一個對象是偶爾的使用,並且希望在使用時隨時就能獲取到,但又不想影響此對象的垃圾收集,那麼應該用 Weak Reference 來記住此對象。或者想引用一個對象,但是這個對象有自己的生命週期,你不想介入這個對象的生命週期,這時候就應該用弱引用,這個引用不會在對象的垃圾回收判斷中產生任何附加的影響。

5 虛引用(PhantomReference)
  • 虛引用和前面的軟引用、弱引用不同,它並不影響對象的生命週期
  • 在任何時候都可能被垃圾回收器回收(對象與虛引用關聯和不關聯效果一樣)
  • 虛引用主要用來跟蹤對象被垃圾回收的活動
  • 虛引用必須和引用隊列關聯使用
  • 在 Java 中用 java.lang.ref.PhantomReference類 表示
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章