匿名监听器是否与弱引用不兼容?

时间:2011-12-12 14:15:03

标签: java callback garbage-collection anonymous-methods

我正在读这个问题: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来说是否合格?

2 个答案:

答案 0 :(得分:6)

是的,你是对的,一个可监听的类维护带有弱引用的侦听器(就像WeakHashMap一样)需要它们的独立持久性。可用于侦听器具有子级和父级的侦听器层次结构。

对于非WeakReference用法,必须调用显式的removeListener。除非侦听器对象可以与可听对象一样长。在大多数用例中都很好,而匿名类也可以。

对于匿名类实例,只有在访问类体外的最终对象时,才会发生泄漏(GC预防)。

注意:WeakHashMap i.a.对自己的Map.Entry子类使用弱引用。这有时可能令人难以置信。

答案 1 :(得分:3)

如果一个对象只是WeakHashMap的一个键,那么它就有资格并且很可能在下一个GC上清理。

使用Weak引用集合的整个想法是隐式删除不再引用的侦听器。 (这可以避免内存泄漏的可能性)问题是可以在“随机”时间点过早地删除侦听器。