Является ли пространство PermGen когда-либо уменьшающимся?

Я хотел бы знать, нормально ли JVM разгружает классы, чтобы уменьшить пространство PermGen. Итак, вот мои вопросы:

  • Разделяют ли классы Java по умолчанию от JVM?
  • Закрывает ли JAR класс загрузчик всех загруженных классов из этой банки?
  • Какие команды/способы должны использоваться для разгрузки классов?

FYI, я действительно пытался использовать некоторые из решений в Интернете, но никто из них не ответил на мои вопросы. (например: Что действительно делает флаг JVM CMSClassUnloadingEnabled?)

PS: Я имею в виду Java 6 + hibernate (загрузка класса обрабатывается спящим режимом)

Ответ 1

Спящий режим загружает все классы Entity в память при запуске SessionFactory. С другой стороны, Entity istances загружаются Hibernate по lazy, только при необходимости.

Классы могут быть выгружены с помощью GC, когда требуется JVM память. Сущности - это сбор мусора, но, как и любой другой объект, только тогда, когда на них больше нет ссылок. Другими словами, Entity istances не могут быть выгружены, если сеанс Hibernate все еще открыт. Чтобы разгрузить их, вам необходимо очистить контекст персистентности или закрыть сеанс.

Ответ 2

Единственный способ избавиться от загруженных классов - позволить JVM GC загрузчику классов, который загружал эти классы, исключив все ссылки на этот загрузчик классов. Это то, что происходит на веб-серверах, когда мы удаляем webapp.

Ответ 3

В настоящее время постоянное поколение собирается по умолчанию.

Постоянное поколение состоит из одного пространства, но не имеет собственного коллектора. Вместо этого это пространство собирается как часть старого поколения.

В соответствии с этой страницей visualgc.

В старых JVM вы можете включить это с помощью флага -XX:+CMSPermGenSweepingEnabled.

классы AFAIK выгружаются, если на них не ссылаются ни один ClassLoader.

Ошибки

java.lang.OutOfMemoryError: PermGen space являются причиной утечек памяти в загрузчиках классов. Общая проблема при развертывании/перераспределении веб-приложений.

Ответ 4

Предполагаем, что вы говорите о HotSpot, Oracle/Sun JVM.

  • Если ссылок на них нет. Обратите внимание, что все классы имеют ссылку на их загрузчик классов и наоборот, и все объекты имеют ссылку на их класс.
  • Может быть. Что вы подразумеваете под "закрытием"?
  • Запустите JVM с параметрами -XX:+UseConcMarkSweepGC и -XX:+CMSClassUnloadingEnabled. Это позволит выгрузить неиспользуемые классы, даже если их загрузчик классов все еще существует.

См. также Разгрузка классов в java?