Что вызывает PermGen OutOfMemoryError на JBoss?

8

Какова основная причина ошибки PermGen OutOfMemoryError в JBoss?

Я использую JBoss AS 4.2.2 в своей среде разработки, и это происходит после многократного повторного развертывания моего веб-приложения.

Блог Christian Жилет Хансен дает возможность виртуальной машины Java , которые помогают много , но не решает проблему полностью:

-XX:+UseConcMarkSweepGC
-XX:+CMSPermGenSweepingEnabled
-XX:+CMSClassUnloadingEnabled
-XX:MaxPermSize=128m
Питер Хилтон
источник

Ответы:

5

Как уже упоминалось, вы, вероятно, испытываете утечку классов загрузчиков. По какой-то причине ваши классы не выгружаются. Это может произойти по двум причинам

  • Объекты указанных классов все еще существуют в куче, объекты всегда ссылаются на их класс, или
  • На загрузчик классов ссылаются где-то, по какой-то причине загрузчики классов ссылаются на свои классы, чтобы не загружать их дважды

Там нет всеобъемлющего решения этой проблемы. Одним из полезных инструментов, который поможет вам найти основную причину, является Eclipse Memory Analyzer Tool , который вы можете применить к дампу кучи из вашей JVM (вы можете включить дампы кучи в OOM с помощью опции -XX: + HeapDumpOnOutOfMemoryError). Возможно, начните искать объекты java.lang.Class в вашем веб-приложении, чтобы понять, почему они остаются живыми. К сожалению, PermGen обычно не является частью дампа кучи JVM, поэтому вы можете только попытаться найти коррелирующие артефакты в остальной части кучи (объекты класса не хранятся в PermGen, если я не ошибаюсь, только действительный байт-код, пожалуйста, поправьте меня, если я ошибаюсь).

НТН.

Редактировать:
Дейв Чейни в комментарии предполагает, что java.lang.Class-объекты действительно являются частью PermGen и не включены в обычный дамп кучи горячей точки. Если у вас нет JVM, которая записывает эту информацию в дамп кучи, вам потребуется другой подход. Вы по-прежнему можете искать экземпляры своих объектов, но если вы пропускаете классы / загрузчики классов (они, к сожалению, подразумевают друг друга), вам, вероятно, нужно искать другие признаки (объекты метаданных из JBoss и т. Д.).

falstro
источник
1
Я почти уверен, что объекты Class хранятся в PermGen (то есть объектах, которые являются экземплярами Class). В Sun JVM есть отдельная область, которая называется Code Cache, где хранится код, скомпилированный в машинный код. И PermGen, и Code Cache являются частью памяти Non Heap, которую можно увидеть с помощью таких инструментов, как jconsole
Дейв Чейни,
@ Дейв Чейни: Ты прав. Утечка объектов класса, застрявшая в PermGen, обычно является причиной проблемы ОП.
Эдди
ига, хотя я не думаю, что содержимое PermGen записывается в дамп кучи (это использует Sun JVM, у меня нет большого опыта работы с остальными), формат дампа hprof наверняка знает такие вещи, как, сколько загружено классов, сколько загрузчиков классов и т. д. Это можно увидеть при открытии hprof в Eclipse Memory Analyzer). Вероятно, что не записано, это большие двоичные данные класса, которые составляют байт-код java. В дампе кучи вы видите «заглушку» экземпляра Class, хранящегося в PermGen.
Дейв Чейни
2

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

Существует хорошая, abeit комплекс объяснение здесь

Дейв Чейни
источник
1

Причиной ошибки PermGen OutOfMemory является повторное развертывание приложения. Основная причина - утечка объектов класса в PermGen из повторных развертываний.

Конечно, обходной путь должен перезапустить JVM после определенного числа повторных развертываний.

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

  • все запущенные вами потоки останавливаются
  • все запущенные вами ThreadPools закрыты
  • все статические ссылки, которые вы можете освободить, освобождаются

Это некоторые из вещей, которые могут вызвать захват объекта Class в PermGen.

Также обратите внимание, что не все JVM (или все версии JVM) будут объектами GC Class в PermGen. Если вы используете JVM или версию JVM, которая не будет объектами GC Class в PermGen, тогда ваш единственный выбор - перезапустить JVM после определенного числа повторных развертываний. Это, вероятно , не относится к вам, учитывая упомянутые вами параметры JVM.

Эдди
источник