Постоянная генерация: емкость значения по умолчанию будет фиксированной или будет расти по мере необходимости?

Мы замечаем, что у нашего клиента, работающего под управлением Solaris 10, постоянный GC увеличивается с 50% до 97% емкости. Эта JVM использовала значение по умолчанию "permgen" (мы НЕ передавали какой-либо пользовательский флаг Permgen в JVM).

Должны ли мы установить более высокое значение PermGen, вместо того, чтобы использовать в производственном пространстве 97% permgen?

PS: мы используем JDK 1.6.0_23 на Solaris 10.

ОБНОВЛЕНИЕ Должны ли мы думать, что в ближайшее время может произойти ошибка OutOfMemoryError? ИЛИ возможно ли, что JVM увеличит емкость, чтобы использование упало ниже 97%?

6 ответов

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

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

Например, мы часто видим проблемы при запуске веб-приложения в Apache Tomcat, который использует Spring и log4j, если экземпляр веб-приложения перезагружается слишком много раз, по-видимому, у log4j есть некоторые проблемы, когда он должным образом не выгружает определенные классы из загрузчика классов.

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

Я полагаю, что JVM будет использовать ту же стратегию для расширения кучи permgen, что и для обычной кучи.

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

Теперь, если куча permgen заполнена на 97% после GC, весьма вероятно, что permgen уже был расширен до максимального настроенного размера (по умолчанию в вашем случае).

Невозможно сказать, где неизбежен ООМ. (Это зависит от того, как ваше приложение ведет себя и что заставляет его увеличивать использование permgen.) Однако было бы разумно:

  • увеличить максимальный размер кучи permgen в краткосрочной перспективе, и
  • отследить, что вызывает увеличение использования кучи permgen.

Мы отмечаем, что у нашего клиента, работающего под управлением Solaris 10, постоянный рост GC увеличился с 50% до 97% емкости.

Произошло ли существенное изменение кода в приложении вашего клиента до того, как он заметил всплеск количества пользователей? Или так было всегда (от 50% до 97%)?

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

Одно можно сказать наверняка, что работа на 97% слишком близка к максимальной для комфорта, и вам придется играть с максимальными параметрами perm gen (и, как следствие, с другими параметрами кучи... скорее всего.)

Эта JVM использовала значение по умолчанию "permgen" (мы НЕ передавали какой-либо пользовательский флаг Permgen в JVM).

Не хорошая идея. Вы должны (прочитайте обязательно) всегда характеризовать ваши (или ваших клиентов) приложения перед развертыванием. Либо ваши клиенты должны сообщить вам, какие параметры им нужны, либо ваша команда должна определить их во время UAT и циклов тестирования системы (при условии, что у вас есть эти параметры, см. Выше).

Должны ли мы думать, что в ближайшее время он может сделать ошибку OutOfMemoryError?

Это не неизбежно, но это возможно (особенно если приложение еще не подверглось максимально возможной нагрузке). Также возможно, если всплеск является недавним явлением. В этом случае, скорее всего, из-за изменения кода или ранее неизвестного состояния из-за других факторов (исправление в ОС, в контейнере, изменение трафика клиента, изменение в БД и т. Д.)

Должны ли мы установить более высокое значение PermGen, вместо того, чтобы использовать в производственном пространстве 97% permgen?

ИМО, да. Если вы (или ваш клиент) можете охарактеризовать или оценить требования к памяти приложения (как перманентной, так и кучи) (а также текущий и возможный будущий трафик), вы должны на всякий случай предоставить себе маржу в 10%-20%. Все, что меньше, это просто игра с огнем. Все, скорее всего, будет расточительным.

Память может быть дешевой, но производительность и стабильность приложений - нет;)

Если вы не используете visualgc, вам следует. Это хороший инструмент для визуальной проверки того, что происходит с различными сегментами в вашей памяти JVM. Существует также VisualVM, который является более мощным и универсальным, но представление показаний интерфейса пользователя VisualGC специально подходит для этой задачи.

PS: мы используем JDK 1.6.0_23 на Solaris 10.

Я не думаю, что это должно иметь значение. Что такое контейнер вашего приложения (если ваше приложение запущено в одном из них). Возможно, вы захотите отредактировать ваше сообщение, чтобы включить это.

Ваши рассуждения немного неясны.

Если вы предвидите неудачу, почему бы не принять защитный подход и увеличить -XX:MaxPermSize сразу?

Существует максимальный размер PermGen, и вы получаете OutOfMemoryError, когда этот si достиг. Однако, если вы заполнены на 97%, это не означает, что вы достигли максимума, просто 97% места, выделенного в это время. (Еще на 3% он должен будет увеличить пространство, если сможет)

Другие вопросы по тегам