Проблемы PermGen с подъемником и причалом
Я развиваюсь на стандартной платформе Lift (maven и причал). Я неоднократно (раз в пару дней) получаю следующее:
Exception in thread "[email protected]" java.lang.OutOfMemoryError: PermGen space
2009-09-15 19:41:38.629::WARN: handle failed
java.lang.OutOfMemoryError: PermGen space
Это в моей среде dev. Это не проблема, потому что я могу продолжать перезагружать сервер. В развертывании у меня таких проблем нет, так что это не настоящая проблема. Мне просто интересно.
Я не слишком много знаю о JVM. Думаю, я прав, думая, что память постоянного поколения для таких вещей, как классы и интернированные строки? То, что я помню, немного смешано с моделью памяти .NET...
Любая причина, почему это происходит? Являются ли дефолты просто безумно низкими? Это связано со всеми вспомогательными объектами, которые Scala должен создавать для объектов Function и подобных FP-вещей? Каждый раз, когда я перезапускаю Jetty с новым кодом (каждые несколько минут), я предполагаю, что он перезагружает классы и т.д. Но даже в этом случае не может быть так много? И не должна ли JVM иметь дело с большим количеством классов?
Приветствия
Джо
Ответы
Ответ 1
От этот пост:
Это исключение произошло по одной простой причине:
permgenspace
, где свойства класса, такие как методы, поля, аннотации, а также статические переменные и т.д. хранятся в виртуальной машине Java, но это пространство имеет особенность не очищаться с помощью уборщик мусора. Поэтому, если ваш webapp использует или создает много классов (Im думает о динамических поколениях классов), скорее всего, вы столкнулись с этой проблемой. Вот некоторые решения, которые помогли мне избавиться от этого исключения:
-
-XX:+CMSClassUnloadingEnabled
: этот параметр позволяет сборку мусора в permgenspace
-
-XX:+CMSPermGenSweepingEnabled
: позволяет сборщику мусора удалить даже классы из памяти
-
-XX:PermSize=64M -XX:MaxPermSize=128M
: увеличивает объем памяти, выделенной для permgenspace
Возможно, это поможет.
Редактировать Июль 2012 (почти 3 года спустя):
Комментарии Ondra Žižka (и я обновил ответ выше):
JVM 1.6.0_27 говорит: Пожалуйста, используйте:
-
CMSClassUnloadingEnabled
(Разрешена ли разгрузка классов при использовании CMS GC)
- вместо
CMSPermGenSweepingEnabled
в будущем
См. полный Параметры JVM Hotspot - полная ссылка для mroe.
Ответ 2
Если вы видите это при запуске mvn jetty:run
,
установите MAVEN_OPTS
.
Для Linux:
export MAVEN_OPTS="-XX:+CMSClassUnloadingEnabled -XX:PermSize=256M -XX:MaxPermSize=512M"
mvn jetty:run
Для Windows:
set "MAVEN_OPTS=-XX:+CMSClassUnloadingEnabled -XX:PermSize=256M -XX:MaxPermSize=512M"
mvn jetty:run
Теперь должно быть хорошо. Если нет, увеличьте -XX:MaxPermSize
.
Вы также можете поместить их в свою среду.
Ответ 3
Это из-за перезагрузки классов, как вы предложили. Если вы используете множество библиотек и т.д., Сумма классов будет быстро расти для каждого перезапуска. Попробуйте контролировать экземпляр вашего причала с помощью VisualVM, чтобы получить обзор потребления памяти при перезагрузке.
Ответ 4
Список рассылки (http://groups.google.com/group/liftweb/) является официальным форумом поддержки для Lift, и где вы сможете получить лучшее ответ. Я не знаю подробностей вашей установки dev (вы не вникаете в детали), но я предполагаю, что вы перезагружаете свою войну в Jetty, не перезапуская ее. Подъем не выполняет динамическое генерирование классов (как предложено VonC выше), но Scala компилирует каждое закрытие как отдельный класс. Если вы добавляете и удаляете замыкания на свой код в течение нескольких дней, возможно, что слишком много классов загружаются и никогда не выгружаются и не занимают перманентное пространство. Я предлагаю вам включить опции JVM, упомянутые выше VonC, и посмотреть, помогают ли они.
Ответ 5
Постоянное поколение - это то, где JVM помещает материал, который, вероятно, не будет (мусор), собранным как пользовательские загрузчики классов.
В зависимости от того, что вы развертываете, настройка perm gen может быть низкой. Некоторые комбинации приложений и/или контейнеров содержат некоторые утечки памяти, поэтому, когда приложение становится незадействованным, иногда некоторые вещи, такие как загрузчики классов, не собираются, что приводит к заполнению Perm Space, создавая при этом вашу ошибку.
К сожалению, в настоящее время лучшим вариантом в этом случае является максимальное увеличение пространства perm со следующим флагом jvm (пример для размерного размера 192 м):
-XX:MaxPermSize=192M (or 256M)
Другой вариант заключается в том, чтобы убедиться, что контейнер или инфраструктура не утечка памяти.