首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JVM 垃圾收集深度解析(三):可觸及性、引用類型與引用隊列

     編輯:Java 相關知識

對象可觸及性的生命週期

JVM 1.2 以前,堆中對象僅分三種狀態:可觸及、可復活、不可觸及。1.2 版本引入四種強弱引用層級,精細控制對象生命週期:

  1. 強可觸及:根節點直接引用或透過強引用鏈路可達,GC 絕不回收。
  2. 軟可觸及:SoftReference 引用,記憶體不足時才回收,適合快取。
  3. 弱可觸及:WeakReference 引用,GC 掃描到即回收,適合規範映射(如 WeakHashMap)。
  4. 影子可觸及:PhantomReference 引用,對象即將被回收,get() 永遠返回 null,用於比 finalize 更靈活的清理。
  5. 引用隊列機制

    ReferenceQueue 讓應用程式異步感知可觸及性變化。建立引用時關聯隊列:

    ReferenceQueue<Cow> queue = new ReferenceQueue<>();
    SoftReference<Cow> ref = new SoftReference<>(new Cow(1), queue);
    

    GC 改變引用狀態時會將引用物件入隊。提供兩種取值方式:

    • poll():非阻塞,無元素立即返回 null。
    • remove():阻塞等待,直到有元素。

    三種弱引用的 GC 處理差異

    引用類型回收時機清除引用入隊時機典型用途
    SoftReference記憶體不足時是清除後記憶體敏感快取
    WeakReference下次 GC 時是清除後規範映射、監聽器快取
    PhantomReference即將回收時否(需手動 clear)立即資源釋放、最終化替代

    代碼演示:監聽引用隊列

    public class TestReference {
        public static void main(String[] args) throws InterruptedException {
            ReferenceQueue<Cow> queue = new ReferenceQueue<>();
            SoftReference<Cow> ref1 = new SoftReference<>(new Cow(1), queue);
            final SoftReference<Cow> ref2 = new SoftReference<>(new Cow(2), queue);
    
            System.out.println(queue.poll()); // null
            ref1.enqueue(); // 手動入隊演示
            System.out.println(queue.poll().get()); // Cow 1
    
            new Thread(() -> {
                try {
                    System.out.println(queue.remove().get()); // 阻塞等待 Cow 2
                    System.out.println("線程獲取到了引用隊列中的對象");
                } catch (InterruptedException e) { e.printStackTrace(); }
            }).start();
    
            Thread.sleep(3000);
            ref2.enqueue();
        }
    }
    class Cow { private int num; public Cow(int n){num=n;} public String toString(){return "This is Cow "+num;} }
    

    輸出:

    null
    This is Cow 1
    等待 3 秒鐘後把 cow2 編入隊列...
    This is Cow 2
    線程獲取到了引用隊列中的對象

    實務應用建議

    • 快取場景優先使用 SoftReference,配合 ReferenceQueue 清理過期項目。
    • 需確保 Key/Value 在無強引用時自動移除,用 WeakHashMap 或自行管理 WeakReference。
    • 避免使用 finalize(),改用 PhantomReference + ReferenceQueue 實現確定性資源釋放。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved