Какая бесплатная реализация JVM лучше всего обрабатывает PermGen?

Я запускаю Tomcat6 в Sun JRE6, и после каждой пары развертываний я получаю OutOfMemoryException: PermGen. Я погуглил по решениям PermGen и попробовал много исправлений. Ни одной работы. Я читал много хороших отзывов о Oracle JRockit и о том, как его PermGen-распределение может иметь размер гига (по сравнению с Sun 128M), и, хотя это не решает проблему, это позволило бы мне выполнить повторное развертывание 100 раз между исключениями PermGen по сравнению с 2 раз сейчас.

Проблема с JRockit заключается в том, что для использования его в производстве вам необходимо купить WebLogic, который стоит тысячи долларов. Какие существуют другие (бесплатные) варианты, более щадящие расширение PermGen? Как следующие JVM работают в этой области?

  • IBM JVM
  • Откройте JDK
  • Blackdown
  • Каффе

... другие?

Обновление: Некоторые люди спрашивают, почему я думал, что PermGen max составляет 128M. Причина в том, что каждый раз, когда я пытаюсь поднять его выше 128M, моя JVM не может инициализироваться:

[2009-06-18 01:39:44] [info] Error occurred during initialization of VM [2009-06-18 01:39:44] [info] Could not reserve enough space for object heap [2009-06-18 01:39:44] [395 javajni.c] [error] CreateJavaVM Failed

Странно, что он не пытается зарезервировать место для объекта куча, хотя я не уверен, что это «куча», а не «куча».

Я загружаю JVM с начальной загрузкой 1024 МБ и максимальной кучей 1536 МБ.

Я закрою этот вопрос, так как на него был дан ответ, т.е. "переключение бесполезно" и вместо этого спросите Почему моя Sun JVM не работает с большими настройками PermGen?


person Robert Campbell    schedule 17.06.2009    source источник


Ответы (7)


Я согласен с Майклом Боргвардтом в том, что вы можете увеличить размер PermGen, я не согласен, что это в первую очередь из-за утечек памяти. Пространство PermGen агрессивно поглощается приложениями, интенсивно использующими Reflection. Так что в основном, если у вас есть приложение Spring / Hibernate, работающее в Tomcat, будьте готовы значительно увеличить это пространство PermGen.

person ThaDon    schedule 17.06.2009
comment
Точно. Традиционные утечки памяти не могут происходить из-за GC, но PermGen обычно не является GC. Я использую как Spring, так и Hibernate, которые интенсивно используют отражение. - person Robert Campbell; 18.06.2009
comment
Не думаю, что это правда. Я не понимаю, почему просто использование отражения требует выделения памяти в PermGen, но я пойду и протестирую это. Spring и Hibernate интенсивно используют прокси, но вы должны увидеть, как это стабилизируется. Точно так же Tomcat будет использовать PermGen при компиляции JSP, но опять же, через некоторое время это все равно должно утихнуть (бесполезно, если у вас включено что-то вроде Always Compile JSP). В любом случае неофициальные данные свидетельствуют о том, что можно запустить полный стек j2ee на jvm от Sun без его сбоя ... - person CurtainDog; 15.04.2010

Что натолкнуло вас на мысль, что JVM Sun ограничена 128M PermGen? Вы можете свободно установить его с помощью параметра командной строки -XX: MaxPermSize; по умолчанию - 64M.

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

person Michael Borgwardt    schedule 17.06.2009
comment
Я прочитал эту статью, но она не дает ничего практически полезного по поводу чего-то, кроме какого-то дурацкого микро-примера. OP просто нужно привыкнуть к этому и не тратить время на то, чтобы это исправить. - person GreenieMeanie; 17.06.2009
comment
Либо вы не прочитали вторую статью, либо не поняли. - person Michael Borgwardt; 18.06.2009
comment
Загрузчики классов на самом деле не так уж и сложны ... но люди, кажется, очень боятся их. - person CurtainDog; 15.04.2010

Технически пул памяти PermGen - это Sun JVM. Другие JVM не называют это так, но все они имеют представление об одном или нескольких пулах памяти без кучи.

Но если у вас есть проблема с permgen в вашей Sun JVM, переход на другую JVM вряд ли что-то решит, он просто проявится под другим именем.

Если несколько повторных развертываний вызывают ваши проблемы, просто увеличьте PermGen виртуальной машины до больших значений. Некоторое время назад мы пробовали JRockit из-за этой самой проблемы, и он страдает от того же недостатка повторного развертывания. Мы вернулись к SUn JVM.

person skaffman    schedule 17.06.2009
comment
Спасибо, я ищу именно такой опыт. Первоначально я смотрел на JRockit, потому что люди утверждали, что вы можете увеличить его PermGen-эквивалент до гигабайт, по крайней мере, допуская более длительные промежутки времени между взрывами. - person Robert Campbell; 18.06.2009

Смена JVM - не панацея. Вы можете получить новые неожиданные проблемы (например, см. статью про запуск приложения под 4 разными JVM).

  • У вас может быть утечка класса (например, через загрузчики классов), что чаще всего происходит при повторном развертывании. Честно говоря, я никогда не видел работающего горячего повторного развертывания на Tomcat (надеюсь когда-нибудь увидеть).
  • У вас могут быть неправильные параметры JVM (например, для Sun JDK 6 64 бит -XX: + UseParNewGC switch приводит к утечке сегмента PermGen памяти. Если вы добавляете дополнительные переключатели: -XX: + UseConcMarkSweepGC -XX: + CMSClassUnloadingEnabled-XX: + CMSPermGenSweeping ситуация разрешится (смешно, но я никогда не встречал вышеупомянутой утечки с Sun JDK 6 32 бита). Ссылка на статью «Настройка сборки мусора JVM для производственных развертываний».
  • Чанка PermGen может быть недостаточно для загрузки классов и связанной с ними информации (на самом деле это чаще всего происходит после повторного развертывания под Tomcat, старые классы остаются в памяти, а новые загружаются)

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

[ОБНОВЛЕНО]

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

person FoxyBOA    schedule 17.06.2009
comment
Проведенное мною исследование заставляет меня думать, что я ничего не могу сделать, кроме сброса Spring, Hibernate, log4j и некоторых других фреймворков. Все они способствуют возникновению этой проблемы. Единственная альтернатива - переместить все их библиотеки в каталог common / lib Tomcat, чтобы они не перезагружались при повторном развертывании. - person Robert Campbell; 18.06.2009
comment
Другой вариант - переключиться на сервер приложений на основе модулей (например, на основе OSGI), например, springsource.org/dmserver - person FoxyBOA; 18.06.2009

Я использую JRockit, и я все равно получаю ошибки PermGen, если я не увеличиваю (через -XX: MaxPermSize) память. Я также не могу заставить ничего работать, чтобы избежать этого (кроме увеличения).

person GreenieMeanie    schedule 17.06.2009
comment
JRockit не имеет постоянного пространства, поэтому я не понимаю, как это может стать лучше, если вы увеличите его с помощью -XX: MaxPermSize? Если вы запустите JRockit с -XX: MaxPermSize, вы получите следующее предупреждающее сообщение: [WARN] -XX: MaxPermSize не является допустимым параметром виртуальной машины. Игнорирование Вы действительно запускали свое приложение с JRockit? - person Kire Haglin; 18.06.2009

Perm gen, вероятно, является самой простой памятью в обращении, я сомневаюсь, что между различными реализациями vm будет большая разница.

Убедитесь, что все конфигурации Tomcat, отмеченные как выключенные в рабочей среде, отключены в рабочей среде.

Да, некоторые фреймворки, которые действительно генерируют много классов на лету, но они должны убирать за собой, и, в любом случае, вы можете разместить больше, чем несколько классов в 128 Мб.

Серьезно, если перманентная генерация продолжает расти, то эту утечку следует исправить, хотя, возможно, это не ваша проблема.

person CurtainDog    schedule 18.06.2009

У IBM JVM нет (и не было в 2009 году) пермген. Вы можете узнать больше о его Generational Concurrent Garbage Collector, который является его сборщиком мусора по умолчанию для Java 7.

Иногда я запускал Eclipse IDE на IBM JVM специально потому, что мои любимые плагины часто заполняли перманент HotSpot JVM. Конечно, вероятно, произошла утечка памяти, которую кто-то должен был исправить, но тем временем моя IDE не вылетала, и я не был занят экспериментами с другими настройками.

person ajm475du    schedule 10.03.2014