Назад | Перейти на главную страницу

Различное потребление памяти при аналогичных конфигурациях

У меня есть два разных экземпляра tomcat 7 на двух разных серверах (oracle jdk7) с почти одинаковой конфигурацией оборудования (оба> 24 ГБ ОЗУ). Оба сервера tomcat имеют одинаковую конфигурацию, и на этих серверах развернуты одни и те же веб-приложения. Catalina предлагает следующие варианты:

-XX:PermSize=128m -XX:MaxPermSize=512M -Xmx2048m -XX:+CMSIncrementalMode -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC

При запуске нагрузочного теста (нагружая REST API с тяжелыми параллельными выполняемыми запросами) один из серверов выдает java.lang.OutOfMemoryError: Java heap space (вот трассировка стека: http://pastebin.com/wuS1MVCC), другой сервер работает нормально. Понятия не имею, почему это происходит. Кто нибудь сталкивался с подобной проблемой?

Итак, что происходит, так это то, что одна из ваших JVM Tomcat пытается превысить размер кучи 2048 МБ, выделенной для нее.

Похоже, вы ищете конкретный ответ, а не только контрольный список вещей, которые нужно попробовать, так что вперед:

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

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

Если проблема возникает после обработки определенного количества запросов независимо от параллелизма, значит, у вас утечка памяти. Вам нужно найти его и вернуть память.

В любом случае вам очень поможет хороший анализатор памяти кучи. Есть хорошие коммерческие, такие как YourKit Java Profiler, или бесплатные, например, Eclipse Memory Analyzer. Найдите инструмент, который подходит вам, и узнайте, как его использовать, чтобы узнать, что занимает память. Обратите внимание, что вам не обязательно использовать инструмент для запуска вашей программы - если вы запускаете нагрузочный тест на сервере, вы можете использовать инструмент командной строки jmap из JDK для захвата дампа кучи в файл, а затем используйте свой инструмент для анализа файла дампа. Инструмент покажет вам, какие объекты занимают место в вашей куче.

Там есть что-то разные между двумя системами, иначе поведение не изменилось бы. Обратите внимание, что слишком много времени, проведенного в сборке мусора и слишком мало результата, также может вызвать ошибку. Работа близко к пределам кучи приводит к возникновению проблем с GC.

Чрезмерное время сборки мусора и ошибка OutOfMemoryError

Параллельный сборщик выдаст OutOfMemoryError, если на сборку мусора тратится слишком много времени: если на сборку мусора уходит более 98% общего времени и восстанавливается менее 2% кучи, будет выброшено OutOfMemoryError. Эта функция предназначена для предотвращения запуска приложений в течение длительного периода времени при незначительном прогрессе или отсутствии прогресса из-за слишком маленькой кучи. При необходимости эту функцию можно отключить, добавив параметр -XX: -UseGCOverheadLimit в командную строку.