【JAVA Reference】Java的強引用、軟引用、弱引用和虛引用(一)

我的原則:先會用再說,內部慢慢來。
學以致用,根據場景學源碼


一、概念與區別

  1. Java中4種引用的強度由高到低依次爲:強引用 -> 軟引用 -> 弱引用 -> 虛引用
  2. 用途與區別:
引用類型 被垃圾回收時機 用途 生存時間
強引用 從來不會 對象的一般狀態 JVM停止運行時終止
軟引用 當內存不足前 對象緩存 內存不足時終止
弱引用 GC一看到立刻回收 對象緩存 垃圾回收後終止
虛引用 隨時隨刻 跟蹤對象的垃圾回收 垃圾回收後終止

二、架構

在這裏插入圖片描述
=== 點擊查看top目錄 ===

三、代碼demo

3.1 強引用 Strong Reference

  • 生命週期:JVM 寧願拋出OutOfMemoryError錯誤。

代碼demo:

    Object strongReference = new Object();
public void hello() {
        Object strongReference = new Object();
        // ...
    }

GC回收時機:

  1. strongReference = null,那麼無引用指向該 new Object()。
  2. 方法結束,java方法棧中局部變量被回收。

否則:JVM 寧願拋出OutOfMemoryError錯誤,使程序異常終止,也不會GC該對象來解決內存不足的問題。

=== 點擊查看top目錄 ===

3.2 軟引用 (SoftReference)

  • 生命週期:JVM 拋出OutOfMemoryError錯誤之前,回收這個軟引用指向的對象堆內佔用的空間。

目的:儘可能保留該對象,但是萬不得已沒內存的時候,可以進行回收

GC回收時機:

  1. strongReference = null,那麼無引用指向該 new Object()。
  2. 方法結束,java方法棧中局部變量被回收。
  3. 堆內存不足,準備拋出OutOfMemoryError錯誤之前,處理一波軟引用。

注意:軟引用就算你調用 System.gc() 在內存充足的情況下,也不會回收這個對象的。

場景:瀏覽器的後退按鈕。(緩存數據能保證加載快,但是內存不足的情況下,被回收了,重新去服務器加載也是可以接受的)

代碼demo:

// 獲取瀏覽器對象進行瀏覽
    Browser browser = new Browser();
    // 從後臺程序加載瀏覽頁面
    BrowserPage page = browser.getPage();
    // 將瀏覽完畢的頁面置爲軟引用
    SoftReference softReference = new SoftReference(page);

    // 回退或者再次瀏覽此頁面時
    if(softReference.get() != null) {
        // 內存充足,還沒有被回收器回收,直接獲取緩存
        page = softReference.get();
    } else {
        // 內存不足,軟引用的對象已經回收
        page = browser.getPage();
        // 重新構建軟引用
        softReference = new SoftReference(page);
    }

=== 點擊查看top目錄 ===

3.3 弱引用 (WeakReference)

  • 生命週期:GC一看到,立馬消滅(首次看到標記,下次gc回收)
  • 使用場景:
  1. 一個對象是偶爾(很少)的使用
  2. 一定程度上可以避免內存泄漏(詳看 ThreadLocal類)

【線程】ThreadLocal 剖析 (十四)

  • ThreadLocal.ThreadLocalMap.Entry
public class ThreadLocal<T> {
	static class ThreadLocalMap {
		static class Entry extends WeakReference<ThreadLocal<?>> {
		    Object value;
		    Entry(ThreadLocal<?> k, Object v) {
		        super(k);
		        value = v;
		    }
		}
	}
}
  • Thread
public java.lang.class Thread implements Runnable {
	...     
    ThreadLocal.ThreadLocalMap threadLocals = null;
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
    ...
}

4. 虛引用(PhantomReference)

  • 生命週期:任何時候都可能被GC回收 (如果一個對象僅持有虛引用,那麼它就和沒有任何引用一樣,在任何時候都可能被垃圾回收器回收)

代碼demo:

public class _03_00_TestPhamtonReference {
    public static void main(String[] args) {
        ReferenceQueue<String> referenceQueue = new ReferenceQueue<>();
        PhantomReference<String> phantomReference = new PhantomReference<>("hello",referenceQueue);
        System.out.println(phantomReference.get());
    }
}

輸出:

null

結論:
剛一出來就被消滅

=== 點擊查看top目錄 ===


四、番外篇

下一章節:【JAVA Reference】ReferenceQueue 與 Reference 源碼剖析(二)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章