Являются ли анонимные слушатели несовместимыми со слабыми ссылками? - PullRequest
17 голосов
/ 12 декабря 2011

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

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

«Проблема с этим подходом заключается в том, что у вас не может быть прослушивателя, на который ссылаются только в коллекции, поскольку он исчезнет случайно (на следующем ГХ)» *

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

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

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

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

Ответы [ 2 ]

6 голосов
/ 12 декабря 2011

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

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

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

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

3 голосов
/ 12 декабря 2011

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

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

...