Когда и как отмечается загрузчик классов Java для сборки мусора? - PullRequest
43 голосов
/ 27 февраля 2010

Мы создаем несколько дочерних загрузчиков классов для загрузки в нескольких подприложениях в «контейнер» Java-приложения, создавая прототип горячего развертывания. Когда путь к классу конкретного загрузчика классов изменился (то есть были добавлены, удалены, обновлены jar-файлы), старый загрузчик классов отбрасывается (не ссылается) и создается новый загрузчик классов для нового пути к классу jar-файлов.

После обновления пути к классам, запуска горячего развертывания, мы взяли дамп кучи. Дамп кучи (с использованием Memory Analyzer) указывает на то, что старые загрузчики классов не собирались мусором. Некоторые классы в родительском загрузчике классов кэшировали старые загрузчики классов. Следующие вещи были вызваны для очистки этих кешей:

java.lang.ResourceBundle.clearCache(classLoader);
org.apache.commons.logging.LogFactory.release(classLoader);
java.beans.Introspector.flushCaches();

Даже после очистки вышеуказанных кешей старый загрузчик классов все еще не собирал мусор. Остальные ссылки на загрузчик классов включали следующее:

  • классы, загруженные загрузчиком классов
  • java.lang.Пакет создан самим загрузчиком классов
  • java.lang.ProtectionDomain, созданный самим загрузчиком классов

Все вышеперечисленное является циклической ссылкой в ​​загрузчике классов, которая должна запускать сборку мусора. Я не уверен, почему это не так. Кто-нибудь знает, почему старые загрузчики классов по-прежнему не собирают мусор даже с циклическими ссылками?

1 Ответ

17 голосов
/ 27 февраля 2010

Я всегда слышал, что Classloader разгрузка была проблематичной. Они теоретически собирают мусор, когда нет ссылки на экземпляры объекта, и выгрузка классов не требуется, но на практике это кажется более проблематичным. Тонкие ссылки могут просочиться и помешать исправлению Classloader. На серверах приложений после многочисленных циклов повторного развертывания я иногда получал OutOfMemoryError: PermGen space.

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

Кроме того, я не знаю точно, что вы делаете, но если вы можете подождать до JDK 7, вы могли бы взглянуть на AnonymousClassLoader. Они будут представлены для лучшей поддержки динамического языка, как объясняется в этом посте:

Надеюсь, это поможет вам.

...