【问题标题】:Are anonymous listeners incompatible with weak references?匿名侦听器与弱引用不兼容吗?
【发布时间】:2012-01-18 12:36:42
【问题描述】:

我正在阅读刚刚被问到的这个问题: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 但它只是一个示例展示我通常如何创建一个匿名类来用作侦听器)。

作为一个额外的问题:如果可观察主题使用 Wea​​kHashMap,那么对匿名侦听器的引用何时有资格进行 GC? main 方法何时退出? obs.addObserver 调用一结束?

对于匿名类实例的引用在何处/如何/何时保留/存储/符合 GC 条件,我有点困惑。

很明显,如果我保留一个普通的引用,它就不符合 GC 的条件,但是当它在 WeakHashMap 中时,确切地说侦听器什么时候才符合 GC 的条件?

【问题讨论】:

    标签: java callback garbage-collection anonymous-methods


    【解决方案1】:

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

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

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

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

    【讨论】:

      【解决方案2】:

      如果一个对象只是 WeakHashMap 的一个键,那么它是合格的并且很可能在下一次 GC 时被清理掉。

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

      【讨论】:

      • 感谢您的帮助,我明白了。但我的问题确实与匿名侦听器特别相关:如果我在 WeakHashMap 中引用匿名侦听器,是否还有对该匿名侦听器的引用保存在其他地方?如果不是,那么什么时候才符合 GC 条件?在哪个电话之后?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多