Анонимные слушатели несовместимы со слабыми ссылками?

Я читал только что заданный вопрос: Избегать утечек памяти при обратных вызовах?

И я был очень сбит с толку, пока кто-то не ответил следующее:

«Проблема с этим подходом в том, что у вас не может быть прослушивателя, на который есть только ссылка в коллекции, поскольку он исчезнет случайным образом (при следующем 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? Когда завершается работа метода main? Как только вызов obs.addObserver завершится?

Я немного смущен тем, где / как / когда ссылки на анонимные экземпляры классов хранятся / хранятся / становятся понятными для GC.

Очевидно, что если я сохраняю обычную ссылку, она не подходит для GC, но что, когда она находится в WeakHashMap, когда именно слушатель становится понятным для GC?


person Cedric Martin    schedule 12.12.2011    source источник


Ответы (2)


Да, вы правы, слушаемый класс, поддерживающий слушателей со слабыми ссылками (как и WeakHashMap), требует их независимой персистентности. Может использоваться для иерархий слушателей, где у слушателя есть дочерние элементы и родитель.

Для использования, отличного от WeakReference, должен быть вызван явный removeListener. Если объект-слушатель не может существовать до тех пор, пока объект-слушатель. В большинстве случаев это нормально, и подойдет анонимный класс.

С экземплярами анонимного класса утечка (предотвращение сборки мусора) может произойти только при доступе к конечному объекту за пределами тела класса.

Примечание. WeakHashMap, в т.ч. использует слабые ссылки для своего собственного подкласса Map.Entry. Иногда это может показаться ошеломляющим.

person Joop Eggen    schedule 12.12.2011

Если объект является только ключом WeakHashMap, то он имеет право и, вероятно, будет очищен при следующем сборке мусора.

Вся идея использования коллекции с слабыми ссылками состоит в неявном удалении слушателей, на которые больше нет ссылок. (Это позволяет избежать утечки памяти). Проблема в том, что слушатель может быть удален преждевременно и в "случайный" момент времени.

person Peter Lawrey    schedule 12.12.2011
comment
Спасибо за помощь, я это понимаю. Но мой вопрос действительно относится именно к анонимным слушателям: если я помещаю ссылку на анонимного слушателя в WeakHashMap, есть ли еще одна ссылка на этого анонимного слушателя, хранящаяся в другом месте? Если нет, то в какой момент сборка мусора становится доступной для чтения? После какого звонка? - person Cedric Martin; 12.12.2011