Что можно сделать с исключением «PermGen out of space» в веб-приложении Tomcat-Spring-Hibernate? - PullRequest
22 голосов
/ 14 июля 2009

У нас есть веб-приложение, которое использует 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 в качестве базы данных.

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

Ответы [ 8 ]

19 голосов
/ 14 июля 2009

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

java -XX:MaxPermSize=256m

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

8 голосов
/ 14 июля 2009

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

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

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

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

4 голосов
/ 14 июля 2009

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

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

3 голосов
/ 14 июля 2009

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

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

  • Поместите драйвер JDBC в общий / lib (как сказано в документации tomcat ), а не в WEB-INF / lib
  • Не помещайте регистрацию в общем доступе в WEB-INF / lib, поскольку tomcat уже загружает его
2 голосов
/ 14 июля 2009

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

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

0 голосов
/ 04 октября 2011

Я столкнулся с той же проблемой, и прочитал, что Tomcat является виновником этой ситуации.

Затем я переключился на причал, и все оказалось великолепно, и приложение развертывается / работает, как и ожидалось. Так что если кот не обязателен, я бы предложил Jetty.

0 голосов
/ 14 июля 2009

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

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

0 голосов
/ 14 июля 2009

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

...