Что можно сделать с исключением PermGen out of space в веб-приложении Tomcat-Spring-Hibernate?

У нас есть веб-приложение, которое использует Spring-Hibernate для сохранения данных зарегистрированных пользователей в базе данных Oracle. Приложение отлично работает в среде разработки, но когда мы копируем его в живую среду с гораздо большим объемом данных, оно терпит неудачу. Первоначально приложение запускается нормально, но после нескольких действий возникло исключение «PermGen out of space».

Я начал искать на форумах Google, Spring и Hibernate, но это не помогает. Об этой ошибке много говорят, но для каждого решения есть люди, которые говорят: «Это работает», а другие говорят: «Это не так».

Например, многие предлагают увеличить параметр -XX:MaxPermSize JVM, другие говорят, что это не работает. Есть сообщения, в которых говорится, что необходимо использовать проблему с использованием библиотеки javassist и других, а также библиотеки cglib. Другие говорят, что проблема в cglib.

Мы используем Java1.5_0_09, Spring 2.5 с javaassist3.4.GA, Tomcat 5.5 в качестве веб-контейнера и Oracle 10g в качестве базы данных.

Может ли кто-нибудь объяснить мне, что вызывает эту проблему и как ее решить?


person Community    schedule 14.07.2009    source источник
comment
У вас много строк? Интернированные струны живут в PermGen   -  person bajafresh4life    schedule 14.07.2009


Ответы (8)


-XX:MaxPermSize действительно работает, вам просто нужно получить правильное значение. По умолчанию, я считаю, что это 32 МБ для виртуальной машины в режиме клиента и 64 МБ для виртуальной машины в режиме сервера. Предлагаю установить 256 МБ, если у вас есть память:

java -XX:MaxPermSize=256m

Проблема возникает из-за того, что Spring и Hibernate могут интенсивно использовать классы, созданные во время выполнения, а иногда и много. Все эти сгенерированные классы попадают в пул памяти PermGen, поэтому, если вы используете эти фреймворки, вам часто нужно увеличивать PermGen до больших объемов.

person skaffman    schedule 14.07.2009
comment
И имейте в виду, что это только отодвигает проблему. Если ваше приложение генерирует классы на регулярной основе, вам время от времени придется перезапускать сервер. - person Stroboskop; 14.07.2009
comment
К сожалению, да. Кажется, мы в значительной степени застряли в этом. - person skaffman; 14.07.2009
comment
@skaffman, означает ли это, что любое приложение, созданное на основе Spring и Hibernate, необходимо перезапустить, чтобы предотвратить OOM на PermGen? Я хочу, чтобы мой сервер работал вечно, если только не добавлю новый код. - person Lee Chee Kiam; 24.08.2011
comment
@CK: Скорее всего, да. 100% безотказная работа даже для Google невозможна. Если вы хотите получить более 99% времени безотказной работы, вам понадобится несколько серверов. - person skaffman; 24.08.2011
comment
@skaffman, я тоже борюсь с той же проблемой. Я продолжаю получать проблему с интервалом PermGen. Однако я чувствую это хорошо, теперь я знаю причину. Спасибо за Вашу информацию. - person vissu; 06.07.2012

Вы должны знать, что в некоторых версиях Tomcat возникают утечки памяти при передислокации во время войны. Это случилось со мной на tomcat 6.0.x.

Как было предложено увеличить MaxPermSize, это временное решение для вашей машины разработки - и когда вы получите сообщение об ошибке через 2-3 дня, просто перезапустите сервер. На производстве не все так просто. Таким образом, этот подходит для разработки, но этот подход не работает для производства, где вам следует исправить проблемы с утечкой памяти.

Для обнаружения утечек используйте приложение jconsole, которое поставляется с jdk 1.6 и 1.5. Вы можете выполнить привязку к процессу и наблюдать за использованием памяти с течением времени.

Вы также можете прочитать это:

person Mercer Traieste    schedule 14.07.2009

Я видел эту проблему с Hibernate (используется без Spring). Проблема заключалась в том, что мы создавали экземпляр SessionFactory для каждого пользовательского запроса, а не для создания единственного экземпляра на время существования приложения.

Я использовал профилировщик YourKit, чтобы исследовать это и обнаружить проблему.

person Matthew Murdoch    schedule 14.07.2009

Как говорит скаффман, свойство -XX: MaxPermSize действительно работает, однако иногда у вас может возникнуть основная проблема, когда повышение предела может только отложиться.

Вы видели эту заметку? Однажды это помогло мне решить аналогичную проблему. Подведем итог по ссылке:

  • Поместите драйвер JDBC в common / lib (как документация tomcat говорит), а не в WEB-INF / lib
  • Не помещайте общий журнал в WEB-INF / lib, так как tomcat уже загружает его
person Rich Seller    schedule 14.07.2009

Visual GC, теперь часть JDK 6, дает очень красивое графическое представление памяти в реальном времени. Вы можете увидеть, что происходит с райским пространством, пространством поколений и перманентным пространством. Вы просто не поймете почему.

ОБНОВЛЕНИЕ: это bin / jvisualvm.exe в моем дистрибутиве JDK 1.6.0_13. Дайте ему PID процесса, который вы хотите отслеживать.

person duffymo    schedule 14.07.2009
comment
Это интересно. Пул PermGen, как известно, непрозрачен и не виден интерфейсу отладки JVMTI. Интересно, как Vidual GC там заглядывает? - person skaffman; 14.07.2009

Все ответы здесь относятся к проблеме PermGen, которая возникает из-за нескольких перезапусков веб-приложения, но в этом случае проблема уже возникает при первом развертывании после перезапуска tomcat, поэтому это не может быть проблемой ссылок ClassLoader или общего журнала.

person Community    schedule 14.07.2009
comment
Это не ответ, вам следует отредактировать исходный вопрос и добавить эту информацию. - person Daniel Serodio; 17.01.2012

Если вы работаете на jdk6, вы можете использовать приложение jconsole для отслеживания использования памяти приложением и дальнейшего исследования.

Еще одно направление - использовать профилировщик, я использую JProfiler, и взглянуть на приложение с ним. Он скажет вам, в чем именно заключается проблема.

person Michael Wiles    schedule 14.07.2009