Подтвердить что ты не робот

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

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

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

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

В качестве бонусного вопроса: когда ссылка на анонимного слушателя будет иметь право на GC, если наблюдаемый субъект использует WeakHashMap? Когда основной метод выходит? Как только вызов obs.addObserver закончился?

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

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

4b9b3361

Ответ 1

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

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

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

Примечание: WeakHashMap i.a. использует слабые ссылки для собственного подкласса Map.Entry. Который иногда может быть совершенно ошеломляющим.

Ответ 2

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

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