目錄
1、強引用 Reference
2、軟引用 SoftReference
3、弱引用 WeakReference
4、 虛引用 PhantomReference
5、小結
前言 如果reference類型的資料中存放的數值是另外一塊記憶體的起始位址,就稱這塊記憶體代表着一個引用。為了更好的控制對象的生命周期,提高記憶體使用率,JDK1.2 之後,java擴充了引用的概念,将引用分為 強引用/軟引用/弱引用/和虛引用四種。
- 強引用(Strong Reference) :隻要對象可達就不會被回收,哪怕抛出OOM
- 軟引用(Soft Reference):記憶體不足的時候才回收
- 弱引用(Weak Reference):下次gc的時候就回收;
- 虛引用(Phantom Reference):跟蹤對象什麼時候被回收
1、強引用 Reference
- 類似于"Object obj = new Object()"這類的引用,隻要垃圾強引用存在,垃圾回收器就不會回收掉被引用的對象;
示例:
//強引用
public class {
static Object obj = new Object();
public static void main(String[] args) {
Object obj2 = new Object();//一樣不會被回收
Object obj1 = obj;
obj = null; //注意引用隻是一個位址變量,obj=null, 但是 obj1 = new Object()還存在引用
System.gc();
System.out.println("gc 後:obj1-" + obj1);
System.out.println("gc 後:obj-" + obj);
}
}
回收的情況:
- 1、作用域結束;
- 2、不可達,複制為null;
2、軟引用 SoftReference
- 當記憶體不夠時回收
示例:
public class SoftReferenceTest {
public static void main(String[] args) {
Object obj = new Object();
//在程式發生oom前才會被回收;記憶體不足的時候才會被回收
//并且優先回收長時間空閑的對象
//适合非必須大對象的緩存;
SoftReference softReference = new SoftReference(obj);
System.out.println(softReference.get());
}
}
3、弱引用 WeakReference
- 強度比軟引用更弱,被弱引用關聯的對象隻能存活到下一次垃圾回收gc之前,當發生gc,無論目前的記憶體是否充足,都會gc回收掉弱引用關聯的對象;
使用示例:
@Data
public class Orange {
private String name;
public Orange(String name) {
this.name = name;
}
@Override
protected void finalize() throws Throwable {
System.out.println("finalized~ ");
super.finalize();
}
}
public class WeakOrange extends WeakReference<Orange> {
public WeakOrange(Orange referent) {
super(referent);
}
}
public class WeakReferenceTest {
public static void main(String[] args) {
Orange orange = new Orange("king"); //強引用
String str = "king-zz";
WeakOrange weakOrange = new WeakOrange(orange); //弱引用
orange = null;
WeakOrange weakOrange = new WeakOrange(str); //弱引用-str 此時str不會被回收,因為str在常量池中,gc不會清理常量池
str = null;
System.out.println("gc前 " + weakOrange.get());
System.gc(); // 發生gc
try {
sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("gc 後:" + weakOrange.get());
}
}
運作結果result:
gc前 Orange(name=king)
finalized~
gc 後:null
4、 虛引用 PhantomReference
- 引用基本不影響什麼,做個标記,在垃圾回收前,處理一些事情。
執行個體: 跟蹤對象什麼時候會回收,隻有在gc的時候,才會在虛引用隊列裡取到該值,判斷回收前需要做什麼。
public class PhantomRef {
public static void main(String[] args) throws InterruptedException {
Object obj = new Object();
ReferenceQueue queue = new ReferenceQueue();
//todo 必須是對象和隊列一起使用才OK;
PhantomReference phantomReference = new PhantomReference(obj, queue);
//todo 這裡擷取的值永遠為空,隻有在gc的時候,才會在隊列的取到這個對象的值,做一些資源的關閉清理;
System.out.println("phantomReference1 " + phantomReference.get()); //null
obj = null;
System.gc(); //gc前會将該對象放入到隊列中,然後處理完後再回收
System.out.println("phantomReference2 " + phantomReference.get());
sleep(1000);
System.out.println("queue.poll " + queue.poll());
}
}
5、小結
引用讓我們更好的控制對象的生命周期,更高效的利用記憶體,防止記憶體洩漏。 水滴石穿,積少成多。學習筆記,内容簡單,用于複習,梳理鞏固。