我們知道在Java中除了基礎的資料型別以外,其它的都為引用型別。 而Java根據其生命週期的長短將引用型別又分為強引用、軟引用、弱引用、幻象引用 。
正常情況下我們平時基本上我們只用到強引用型別,而其他的引用型別我們也就在面試中,或者平日閱讀類庫或其他框架原始碼的時候才能見到。
1.強引用
我們平日裡面的用到的new了一個物件就是強引用,例如 Object obj = new Object();
當JVM的記憶體空間不足時,寧願丟擲OutOfMemoryError使得程式異常終止也不願意回收具有強引用的存活著的物件!
記住是存活著,不可能是你new一個物件就永遠不會被GC回收。當一個普通物件沒有其他引用關係,只要超過了引用的作用域或者顯示的將引用賦值為null時,你的物件就表明不是存活著,這樣就會可以被GC回收了。當然回收的時間是不一定的具體得看GC回收策略。
2.軟引用
軟引用的生命週期比強引用短一些。軟引用是通過SoftReference
類實現的。
Object obj = new Object();
SoftReference softObj = new SoftReference(obj);
obj = null; //去除強引用
複製程式碼
這樣就是一個簡單的軟引用使用方法。通過get()
方法獲取物件。當JVM認為記憶體空間不足時,就回去試圖回收軟引用指向的物件,也就是說在JVM丟擲OutOfMemoryError
之前,會去清理軟引用物件。軟引用可以與引用佇列(ReferenceQueue)
聯合使用。
Object obj = new Object();
ReferenceQueue queue = new ReferenceQueue();
SoftReference softObj = new SoftReference(obj,queue);
obj = null; //去除強引用
複製程式碼
當softObj
軟引用的obj
被GC回收之後,softObj
物件就會被塞到queue
中,之後我們可以通過這個佇列的poll()
來檢查你關心的物件是否被回收了,如果佇列為空,就返回一個null
。反之就返回軟引用物件也就是softObj
。
軟引用一般用來實現記憶體敏感的快取,如果有空閒記憶體就可以保留快取,當記憶體不足時就清理掉,這樣就保證使用快取的同時不會耗盡記憶體。例如圖片快取框架中快取圖片就是通過軟引用的。
3.弱引用
弱引用是通過WeakReference
類實現的,它的生命週期比軟引用還要短,也是通過get()
方法獲取物件。
Object obj = new Object();
WeakReference<Object> weakObj = new WeakReference<Object>(obj);
obj = null; //去除強引用
複製程式碼
在GC的時候,不管記憶體空間足不足都會回收這個物件,同樣也可以配合ReferenceQueue
使用,也同樣適用於記憶體敏感的快取。ThreadLocal
中的key就用到了弱引用。
4.幻象引用
也稱虛引用,是通過PhantomReference
類實現的。任何時候可能被GC回收,就像沒有引用一樣。
Object obj = new Object();
ReferenceQueue queue = new ReferenceQueue();
PhantomReference<Object> phantomObj = new PhantomReference<Object>(obj , queue);
obj = null; //去除強引用
複製程式碼
無法通過虛引用訪問物件的任何屬性或者函式。那就要問了要它有什麼用?虛引用僅僅只是提供了一種確保物件被finalize
以後來做某些事情的機制。比如說這個物件被回收之後發一個系統通知啊啥的。虛引用是必須配合ReferenceQueue
使用的,具體使用方法和上面提到軟引用的一樣。主要用來跟蹤物件被垃圾回收的活動。
如有錯誤歡迎指正!
個人公眾號:yes的練級攻略
有相關面試進階(分散式、效能調優、經典書籍pdf)資料等待領取