我正在读这个问题:Avoid memory leaks in callbacks?
我很困惑,直到有人回答以下问题:
“这种方法的问题是你不能有一个只在集合中引用的监听器,因为它会随机消失(在下一个GC上)”
我的理解是正确的,使用弱引用(如存储在 WeakHashMap 中)与匿名侦听器不兼容?
我通常传递这样的听众:
public static void main(String[] args) {
final Observable obs = new SomeObservable();
obs.addObserver(new Observer() {
public void update(final Observable o, final Object arg) {
System.out.println("Notified");
}
});
obs.notifyObservers();
... // program continues its life here
}
private static final class SomeObservable extends Observable {
@Override
public void addObserver(final Observer o) {
super.addObserver(o);
setChanged(); // shouldn't be done from here (unrelated to the question)
}
}
我使用 CopyOnWriteArrayList 跟踪听众(上面的默认 Observable 显然使用了旧的 Vector ,但它只是一个例子来展示我通常如何创建一个匿名类来用作监听器。)
作为一个额外的问题:如果可观察主题使用WeakHashMap,那么对匿名听众的引用何时才符合GC的条件?当 main 方法退出时?一旦 obs.addObserver 调用结束了吗?
我对于保存/存储/忽略对GC的匿名类实例的引用的位置/方式/时间有点困惑。
显然,如果我保持正常参考,它不符合GC的条件,但是当它在WeakHashMap中时,精确地何时,监听器对于GC来说是否合格?
答案 0 :(得分:6)
是的,你是对的,一个可监听的类维护带有弱引用的侦听器(就像WeakHashMap一样)需要它们的独立持久性。可用于侦听器具有子级和父级的侦听器层次结构。
对于非WeakReference用法,必须调用显式的removeListener。除非侦听器对象可以与可听对象一样长。在大多数用例中都很好,而匿名类也可以。
对于匿名类实例,只有在访问类体外的最终对象时,才会发生泄漏(GC预防)。
注意:WeakHashMap i.a.对自己的Map.Entry子类使用弱引用。这有时可能令人难以置信。
答案 1 :(得分:3)
如果一个对象只是WeakHashMap的一个键,那么它就有资格并且很可能在下一个GC上清理。
使用Weak引用集合的整个想法是隐式删除不再引用的侦听器。 (这可以避免内存泄漏的可能性)问题是可以在“随机”时间点过早地删除侦听器。