簡體   English   中英

Java WeakReference GC 已完成,未完成?

[英]Java WeakReference GC finalized , not finalized?

我以為 WeakReference 參考 object 將在 System.gc() 調用后完成,但我錯了。

這里有兩個測試用例,唯一的區別是 WeakReference 構造函數,第一個是新的 object 而第二個使用的是引用,它們有不同的性能,我不知道為什么......

弱引用對象,不會阻止它們的引用對象被最終化、最終化,然后被回收。 弱引用最常用於實現規范化映射。

假設垃圾收集器在某個時間點確定 object 是弱可達的。 屆時,它將自動清除對 object 的所有弱引用以及對任何其他弱可達對象的所有弱引用,通過強引用和軟引用鏈可以從這些弱可達對象中訪問 object。 同時它將聲明所有以前的弱可達對象都是可終結的。 在同一時間或稍后的某個時間,它會將那些在引用隊列中注冊的新清除的弱引用排入隊列。

package com.zeng.javaReference;

import org.junit.Test;

import java.lang.ref.WeakReference;

/**
 * @author zeng
 * @version 1.0.0
 * @date 2020-05-11
 */
public class WeakReferenceTest {

    @Test
    public void weakRefRemoved() {
        WeakReference<Apple> weakReference = new WeakReference<>(new Apple("green-apple"));

        System.gc();

        if (weakReference.get() == null) {
            System.out.println("GC remove weakReference!");
        } else {
            System.out.println("weakReference still alive");
        }
    }

    @Test
    public void weakRefNotRemoved() {
        Apple apple = new Apple("green-apple");
        WeakReference<Apple> weakReference = new WeakReference<>(apple);

        System.gc();

        if (weakReference.get() == null) {
            System.out.println("GC remove weakReference!");
        } else {
            System.out.println("weakReference still alive");
        }
    }

    public static class Apple {

        private String name;

        public Apple(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Override
        protected void finalize() throws Throwable {
            super.finalize();
            System.out.println("Apple: " + name + " finalized。");
        }

        @Override
        public String toString() {
            return "Apple{" +
                    "name='" + name + '\'' +
                    '}' + ", hashCode:" + this.hashCode();
        }
    }

}

System.gc()可能會也可能不會觸發垃圾收集。

通過手動調用它,您只是在向 JVM 提供提示,但它是否會兌現它完全取決於 java 運行時。 JVM 是非常復雜的系統,不允許直接訪問資源。

至於文檔中的WeakReference

弱參考是指其強度不足以使 object 保留在 memory 中的參考。 因此,弱引用可以讓垃圾收集器決定對象的可達性,以及是否應該將有問題的 object 保留在 memory 中。

再次決定收集 object 的天氣完全取決於收集器。

這確實是相當有趣的。

假設您使用的 GC 收集器在調用System.gc()時實際執行了某些操作,例如G1 ,並且您沒有通過-XX:+DisableExplicitGC禁用對 GC 的顯式調用,則不知何故對此有解釋。

理論上, weakRefNotRemoved應該與weakRefRemoved一樣工作。 這與scopereachability有關, 這里有更多詳細信息。

關鍵是在weakRefNotRemoved中,調用System.gc()之后apple引用沒有被任何人使用,所以在那個時候它是不可訪問的。 因此,理論上,GC 可以回收它,但無論出於何種原因,它都不會。 我只能假設這個特殊路徑只有在有真正的 memory 壓力時才會觸發。

為了證明這一點,我們可以稍微修改一下代碼,如下:

 public static void weakRefNotRemoved() {
    Apple apple = new Apple("green-apple");
    WeakReference<Apple> weakReference = new WeakReference<>(apple);

    // explicitly set to null
    apple = null;
    System.gc();

    if (weakReference.get() == null) {
        System.out.println("GC remove weakReference!");
    } else {
        System.out.println("weakReference still alive");
    }
}

現在,GC 確實會清理它。 一般來說,如果你試圖證明一個觀點,最好在 while 循環下調用它,因為不能保證循環會“捕獲” 那個引用 也因為清除以異步方式發生。 就像是:

 public static void weakRefNotRemoved() {
    Apple apple = new Apple("green-apple");
    WeakReference<Apple> weakReference = new WeakReference<>(apple);

    apple = null;
    while (weakReference.get() != null) {
        System.out.println("weakReference still alive");
        System.gc();
        LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
    }

    System.out.println("GC remove weakReference!");

}

而且得到這樣一個output是完全合法的,例如:

weakReference still alive  // zero or more of these messages
GC remove weakReference!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM