首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java GC 回收機制:重新指派 List 參考後舊鏈表節點是否會被回收?

     編輯:程式設計綜合問答

程式碼情境

LinkedList<String> list = new LinkedList<>();
list.add("a"); list.add("b");
list = new LinkedList<>(); // 重新指派
list.add("c"); list.add("d");

結論:舊鏈表**一定會被回收** (若無其他參考)

記憶體圖解

第一次 new LinkedList() → 物件 A (head→Node("a")→Node("b")→null)
list 參考 ──────────────────┘

list = new LinkedList() → 物件 B (head→Node("c")→Node("d")→null)
list 參考 ──────────────────┘

物件 A: 無任何參考指向 → GC Root 不可達 → 標記回收

關鍵點

  • Java **達標式 GC**:從 GC Roots (棧區參考、靜態欄位、JNI 參考) 向下遍歷,**不可達** 物件即為垃圾。
  • 節點間相互參考 (雙向鏈表 prev/next) **不影響** 可達性分析,只要鏈表頭節點不可達,整條鏈即不可達。
  • list = new ... 只是讓區域變數 list 指向新物件,舊物件瞬間失去最後一個 GC Root 參考。

驗證程式碼

public class GCDemo {
    static class Node { 
        Node next; 
        String val;
        Node(String v) { val = v; }
        @Override protected void finalize() { System.out.println("Node " + val + " finalized"); }
    }
    public static void main(String[] args) {
        Node head = new Node("a"); head.next = new Node("b");
        head = new Node("c"); head.next = new Node("d"); // 丟棄 a-b 鏈
        System.gc(); // 請求 GC (不保證立即執行)
        Thread.sleep(1000);
    }
}
// 輸出可能出現: Node a finalized / Node b finalized

最佳實務

  • 不需手動將節點 next=null,現代 GC (G1, ZGC) 能高效處理循環參考。
  • 大量短命物件 (如迴圈中 new List) 建議複用集合 (list.clear()) 或調整新生代大小 (-Xmn)。
  • 記憶體洩漏通常源於 **長生命週期物件持有短命物件參考** (如 static List 不斷 add),而非局部變數重新指派。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved