Как устранить утечку памяти прослушивателя свинга?

Фон

Итак, я прочитал, что часто утечки памяти в приложениях Swing происходят из-за использования различных слушателей (мышь, клавиша, фокус и т. д.). По сути, поскольку вы регистрируете объект в качестве прослушивателя и забываете отменить регистрацию объекта, уведомитель в конечном итоге удерживает ссылку на объект и немного теряет память.

Я знал, что наше приложение не отменяет регистрацию слушателей, и провел небольшое исследование потенциальных решений:

Я обнаружил, что одним из подходов к решению проблемы было использование WeakReference, полную информацию о подходе со свинг-слушателями можно найти здесь.

Затем мне стало любопытно, как редактор форм NetBeans генерирует код для очистки после того, как слушатели добавляли в форму, и обнаружил, что NetBeans регистрировал слушателей через объект-оболочку, т.е.

argTypeComboBox.addItemListener(new java.awt.event.ItemListener() {
    public void itemStateChanged(java.awt.event.ItemEvent evt) {
      argTypeComboBoxItemStateChanged(evt);
    }
});

Но сгенерированный код, похоже, никогда не очищался вызовом removeItemListener.

Вопросы

Объект-обертка действует как слабая ссылка? Мне кажется, что это может привести к утечке небольшого объема памяти (размер объекта-обертки)?

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


person Clinton    schedule 10.12.2009    source источник


Ответы (1)


Сначала поправочка, потенциальная утечка здесь не маленькая. Анонимный внутренний класс содержит ссылку на внешний класс, поэтому, пока прослушиватель доступен, он будет удерживать весь класс.

Однако обычно это не проблема, поскольку вы добавляете слушателей к объектам в кадре. Когда этот фрейм удаляется (важно, чтобы он был удален) и больше не имеет ссылок (что довольно типично), все его компоненты становятся недоступными (если вы не сделали ничего необычного), и все это становится сборщиком мусора.

Однако однажды я имел дело с приложением, которое действительно делало причудливые вещи, такие как регистрация открытых окон с другим окном, поэтому, если окно было закрыто, оно все равно было зарегистрировано — большая утечка памяти — эти окна не были крошечными.

Таким образом, суть в том, что NetBeans не делает ничего, чтобы вызвать «утечку» памяти здесь, поскольку на компонент ссылается фрейм, а не за его пределами, и компонент ссылается на анонимный класс, который, в свою очередь, ссылается на фрейм — избавьтесь от фрейма. и весь граф недоступен, но вы должны быть осторожны со слушателями, так как они могут сделать это с вами.

person Yishai    schedule 10.12.2009
comment
Отличное разъяснение. Ишай, какой подход вы применяли к слушателям в причудливом приложении, в котором произошла большая утечка памяти? - person Clinton; 10.12.2009
comment
@Clinton, как только я диагностировал проблему (это заняло некоторое время, много профилирования), я просто был уверен, что отменю регистрацию прослушивателя при удалении окна. Я не помню всех подробностей, но это было ключевым - я не знал тогда о слабых ссылках как стандартном решении проблемы, возможно, я мог бы использовать это. - person Yishai; 10.12.2009
comment
@Yishai Я делал отмену регистрации, когда слушатель выходил из области видимости ... Но это казалось немного неуклюжим, и я искал лучшее решение. Еще раз спасибо за поправку. - person Clinton; 10.12.2009
comment
Мое текущее программное обеспечение делает то, что вы когда-то имели дело =\ - person SHiRKiT; 11.01.2012