[英]Why is this weak listener not garbage collected?
這是Kishori Sharan的《 Learn JavaFX 8》一書中的一個示例:
package sample;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.beans.value.WeakChangeListener;
public class WeakListener {
public static IntegerProperty counter = new SimpleIntegerProperty(100);
public static WeakChangeListener<Number> weakListener;
public static ChangeListener<Number> changeListener;
public static void main(String[] args) {
// Add a weak change listener to the property
addWeakListener();
counter.set(300);
System.gc();
System.out.println("Garbage collected: " +
weakListener.wasGarbageCollected());
counter.set(400);
changeListener = null;
System.gc();
System.out.println("Garbage collected: " +
weakListener.wasGarbageCollected());
counter.set(500);
}
public static void addWeakListener() {
changeListener = WeakListener::changed;
weakListener = new WeakChangeListener<>(changeListener);
counter.addListener(weakListener);
counter.set(200);
}
public static void changed(ObservableValue<? extends Number> prop,
Number oldValue,
Number newValue) {
System.out.print("Counter changed: ");
System.out.println("old = " + oldValue + ", new = " + newValue);
}
}
在將強偵聽器設置為null之后,應該對弱偵聽器進行GC:
但結果與預期不同:
Counter changed: old = 100, new = 200
Counter changed: old = 200, new = 300
Garbage collected: false
Counter changed: old = 300, new = 400
Garbage collected: false
Counter changed: old = 400, new = 500
我在OSX優勝美地上使用jdk 1.8_u51。
恐怕這篇文章是錯誤的-這是更正的句子:
將其設置為
null
,然后再次調用垃圾回收之后,更改偵聽器可能會被垃圾回收。
本質上,Java中沒有System.gc();
合同System.gc();
。 請參閱此處的措辭,其狀態(我強調):
調用gc方法表明 ,Java虛擬機將花費更多精力來回收未使用的對象,以使它們當前占用的內存可用於快速重用。 當控件從方法調用返回時,Java虛擬機將盡最大努力從所有丟棄的對象中回收空間。
那里什么也沒有說它實際上會收集任何垃圾。
一個簡單但令人失望的答案:System.gc()不會強制進行垃圾回收。 它所做的只是告訴VM現在是收集垃圾的好時機。 VM現在不必運行垃圾收集。
如果VM例如認為有足夠的剩余內存,那么它可能那時不運行垃圾回收。
因此,如果您真的想測試垃圾回收,請提高內存使用率並在更長的時間內多次運行System.gc()。 這樣,您可能會增加收集收聽者的機會。
這里同樣的問題。
我發現只是從方法引用更改了ChangeListener的創建:
changeListener = WeakListener::changed;
到一個普通的匿名老班
changeListener = new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
System.out.print("Counter changed: ");
System.out.println("old = " + oldValue + ", new = " + newValue);
}
};
確實輸出得很好:
Counter changed: old = 100, new = 200
Counter changed: old = 200, new = 300
Garbage collected: false
Counter changed: old = 300, new = 400
Garbage collected: true
哇! 這是與Lambda相關的錯誤嗎? 在JDK8U60中使用Win7 X64
您將在靜態變量weakListener中保留對WeakChangeListener的引用。
僅當對象沒有任何引用時才對其進行垃圾回收。
當您使changeListener無效時,它將保留對weakListener的內部引用,但是只要至少有一個引用,該對象將保留在內存中。
編輯:
我不知道弱引用如何在Java上工作。 如果像我一樣,某人不了解它們,那么https://weblogs.java.net/blog/2006/05/04/understanding-weak-references是不錯的閱讀方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.