以下是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后,弱侦听器应该是GCed:
但结果与预期不符:
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 yosemite上使用jdk 1.8_u51。
答案 0 :(得分:5)
我担心这篇文章是错的 - 这是纠正的句子:
将其设置为
null
然后再次调用垃圾收集后,更改侦听器可能被垃圾收集。
基本上,System.gc();
中没有Java合同。请参阅here措辞中的状态(我的重点):
调用gc方法建议 Java虚拟机花费大量精力来回收未使用的对象,以使其当前占用的内存可用于快速重用。当控制从方法调用返回时,Java虚拟机已尽最大努力从所有丢弃的对象中回收空间。
没有任何声明它会实际收集任何垃圾。
答案 1 :(得分:2)
简单但令人失望的答案:System.gc()不强制垃圾收集。它所做的就是告诉VM现在是收集垃圾的好时机。 VM现在不必运行垃圾回收。
如果是VM,例如我认为,它有足够的内存,当时可能无法运行垃圾收集。
因此,如果您真的想测试垃圾收集,请提高内存使用率并在较长时间内多次运行System.gc()。这样你可能会增加收听者的机会。
答案 2 :(得分:1)
这里也有同样的问题。
我发现只需从方法引用中更改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相关的bug吗? 使用win7 x64和jdk8u60
答案 3 :(得分:0)
您在静态变量weakListener中保留对WeakChangeListener的引用。
当对象没有任何引用时,它只被垃圾收集。
当你使changeListener无效时,它保留给weakListener的内部引用会丢失,但只要至少有一个引用,该对象就会保留在内存中。
编辑:
我不知道弱引用如何在Java上运行。如果像我一样,某人不了解他们,https://weblogs.java.net/blog/2006/05/04/understanding-weak-references是一个很好的阅读。