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類
表示