前言
判斷物件是否要回收有引用計數法和可達性演算法兩種方式,無論哪種都離不開引用,本文將介紹Java的四種引用。
一、概述
二、詳解
1. 強引用
概述
在Java程式中,強引用是最常見的也是預設的。new
了一個物件,並將其指向一個變數,這個變數就成為指向該物件的一個強引用。
特點
- 強引用可以直接訪問目標物件;
- 強引用所指向的物件在任何時候都不會被系統回收;
- 強引用可能導致記憶體洩漏。
實現方式
Object obj = new Object() //這裡的obj就是一個強引用
2. 軟引用
概述
軟引用是用來描述一些還有用,但非必需的物件。只被軟引用關聯著的物件,在系統將要發生記憶體溢位異常前,會把這些物件列進回收範圍之中進行第二次回收,如果這次回收還沒有足夠的記憶體,才會丟擲記憶體溢位異常。
特點
- 軟引用所指向的物件,記憶體溢位前才被系統回收;
- 軟引用被回收後還沒有足夠的記憶體,仍會丟擲記憶體溢位異常;
- GC 決定收回軟可達物件時,會清理軟引用,並可選地把引用存放到一個引用佇列(Reference Queue)。
場景
軟引用通常用來實現記憶體敏感的快取。比如:可以使用軟引用來快取最近使用的圖片或文字,一旦記憶體不足,垃圾回收器就會回收這些物件,從而釋放記憶體。
實現方式
Object obj = new Object(); // 宣告強引用
SoftReference<Object> sf = new SoftReference<>(obj);
obj = null; //銷燬強引用
3. 弱引用
概述
弱引用也是用來描述那些非必需物件,但是在系統GC時,只要發現弱引用,不管系統堆空間使用是否充足,都會回收掉只被弱引用關聯的物件。 (但是,由於垃圾回收器的執行緒通常優先順序很低,因此,並不一定能很快地發現持有弱引用的物件。在這種情況下,弱引用物件可以存在較長的時間。)
特點
弱引用所指向的物件,被發現就會被系統回收;
場景
- 快取中存放的一些臨時的資料。如,ThreadLocal;
- 多執行緒中經常被用來監控物件是否被垃圾回收器標記。
實現方式
Object obj = new Object(); // 宣告強引用
WeakReference<Object> wf = new WeakReference<>(obj);
obj = null; //銷燬強引用
4. 虛引用
概述
所有引用型別中最弱的一個。一個物件是否有虛引用的存在,完全不會決定物件的生命週期。
特點
- 不能單獨使用,虛引用必須和引用佇列一起使用;
- 一個物件只被虛引用變數引用時,垃圾回收器會將該物件加入引用佇列中;
- 無法透過虛引用來獲取被引用的物件(當試圖透過虛引用的get()方法取得物件時,總是null)。
場景
在回收該物件之前,虛引用變數將被放入引用佇列中,因此通常用於在物件被回收時執行必要的清理工作。例如:
- 關閉資料庫連線或釋放資源在併發程式設計中;
- 實現一些高階的物件生命週期管理,例如,物件池和執行緒池等。(追蹤物件的生命週期,並在物件不再使用時及時清理它們,從而保證系統的可靠性和效能)
實現方式
Object obj = new Object(); // 宣告強引用
ReferenceQueue phantomQueue = new ReferenceQueue(); //須和引用佇列一起使用
PhantomReference<Object> pf = new PhantomReference<>(obj, phantomQueue);
obj = null;