Проблемы PermGen с Lift и Jetty
Я занимаюсь разработкой на стандартной платформе Lift (Maven и Jetty). Я неоднократно (раз в пару дней) получаю это:
Exception in thread "7048009@qtp-3179125-12" java.lang.OutOfMemoryError: PermGen space
2009-09-15 19:41:38.629::WARN: handle failed
java.lang.OutOfMemoryError: PermGen space
Это в моей среде разработки. Это не проблема, потому что я могу продолжать перезагружать сервер. В развертывании у меня нет этих проблем, так что это не настоящая проблема. Мне просто интересно.
Я не слишком много знаю о JVM. Я думаю, что я прав, думая, что память постоянного поколения предназначена для таких вещей, как классы и интернированные строки? То, что я помню, немного перепутано с моделью памяти.NET...
Есть причина, почему это происходит? Значения по умолчанию просто безумно низкие? Связано ли это со всеми вспомогательными объектами, которые Scala должен создавать для объектов Function и подобных вещей FP? Каждый раз, когда я перезапускаю Jetty с новым написанным кодом (каждые несколько минут), я представляю, что он перезагружает классы и т. Д. Но даже в этом случае, не может ли быть так много, не так ли? И не должна ли JVM иметь дело с большим количеством классов?
ура
Джо
5 ответов
Из этого поста:
Это исключение произошло по одной простой причине:
permgenspace
это место, где свойства класса, такие как методы, поля, аннотации, а также статические переменные и т. д., хранятся в Java VM, но это пространство имеет особую особенность - не очищаться сборщиком мусора. Так что если ваше веб-приложение использует или создает много классов (я думаю, динамические поколения классов), скорее всего, вы столкнулись с этой проблемой. Вот некоторые решения, которые помогли мне избавиться от этого исключения:
-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
в будущем
См. Полный список параметров Hotspot JVM - полный справочник по mroe.
Если вы видите это при запуске 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
,
Вы также можете поместить их навсегда в вашу среду.
Для Linux добавьте
export
линия к~/.bashrc
Для Windows нажмите
Win-key + PrintScreen
, и идтиAdvanced > Environment
, Смотрите также http://support.microsoft.com/kb/310519.
Это из-за перезагрузки классов, как вы предложили. Если вы используете много библиотек и т. Д., Сумма классов будет быстро расти при каждом перезапуске. Попробуйте контролировать свой экземпляр Jetty с помощью VisualVM, чтобы получить обзор потребления памяти при перезагрузке.
Список рассылки ( http://groups.google.com/group/liftweb/) является официальным форумом поддержки Lift, где вы сможете получить лучший ответ. Я не знаю подробностей вашей настройки разработчика (вы не будете вдаваться в подробности), но я предполагаю, что вы перезагружаете свою войну в Причале, фактически не перезапуская ее. Lift не выполняет динамическую генерацию классов (как предложено выше VonC), но Scala компилирует каждое замыкание как отдельный класс. Если вы добавляете и удаляете замыкания в коде в течение нескольких дней, вполне возможно, что загружается слишком много классов, которые никогда не выгружаются и занимают разрешенное пространство. Я бы посоветовал вам включить опции JVM, упомянутые VonC выше, и посмотреть, помогут ли они.
Постоянное поколение - это то, где JVM помещает вещи, которые, вероятно, не будут (мусор) собираться как пользовательские загрузчики классов.
В зависимости от того, что вы развертываете, настройка perm gen может быть низкой. Некоторые комбинации приложений и / или контейнеров действительно имеют некоторые утечки памяти, поэтому, когда приложение удаляется, иногда некоторые вещи, такие как загрузчики классов, не собираются, что приводит к заполнению пространства Perm, в результате чего возникает ошибка, которая у вас возникла.
К сожалению, в настоящее время лучшим вариантом в этом случае является увеличение пространства perm со следующим флагом jvm (например, для размера perm 192m):
-XX:MaxPermSize=192M (or 256M)
Другой вариант - убедиться, что ни контейнер, ни среда не пропускают память.