В этом случае длинная коллекция мусора java для молодого поколения?

вчера у нас был следующий выход GC в нашем журнале сервера одного сервера приложений JBoss:

51628.286: [GC 51628.288: [ParNew: 1843200K->204800K(1843200K), 21.3196040 secs]
5177730K->3743415K(7987200K), 21.3217870 secs]
[Times: user=1.38 sys=0.33, real=21.32 secs] 

Я понимаю результат следующим образом: молодое поколение размером 1843200K. Размер до поколения был 1843200K, размер после 204800K. Коллекция продолжалась 21,3 секунды.

Обычно наши коллекции молодого поколения продолжаются < 1 с. В каких обстоятельствах коллекции yg длится так долго?

Наши параметры JVM:

-server 
-verbose:gc
-XX:+PrintGCTimeStamps
-XX:+PrintGCDetails 
-XX:NewRatio=3
-XX:+UseConcMarkSweepGC 
-XX:+UseParNewGC 
-XX:+UseCMSCompactAtFullCollection 
-XX:CMSInitiatingOccupancyFraction=60 
-XX:MaxPermSize=256m 
-Xss512k 
-Xms8000m 
-Xmx8000m

версия java:

java version "1.6.0_29"
Java(TM) SE Runtime Environment (build 1.6.0_29-b11)
Java HotSpot(TM) 64-Bit Server VM (build 20.4-b02, mixed mode)

Спасибо, Марсель

Ответ 1

У нас был сервер tomcat, у которого были сборки мусора, которые продолжались ~ 2 минуты. В конце концов, мы нашли причину, мы выделили больше памяти для JVM через -Xmx, чем у нас была физическая память в системе. Это вызывало пейджинг во время сбора мусора, который убивает его.

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

Для получения дополнительной информации см. Настройка системы управления памятью, раздел Настройка размера кучи (мой акцент):

Параметры командной строки: -Xms: -Xmx:

Размер кучи влияет на скорость распределения, сбор мусора частоту и время сбора мусора. Маленькая куча станет полной быстро и должен чаще собираться мусор. Он также больше фрагментации, делая размещение объектов медленнее. Большая куча вводит небольшие накладные расходы на сбор мусора. Куча, которая больше, чем доступная физическая память в системе должна быть выгружается на диск, что приводит к длительному времени доступа или даже к приложение замораживается, особенно во время сбора мусора.

Ответ 2

Вы используете параллельный сборщик мусора (-XX:+UseConcMarkSweepGC), который запускается в отдельном потоке. Из опубликованного вами выпуска Times вы увидите, что сборщик мусора не работал долго. Я бы предположил, что вашей системе не хватило времени процессора для работы GC, поэтому для GC понадобилось 20 с, чтобы получить 1 с времени процессора. При использовании параллельного GC вы должны убедиться, что ваше приложение не потребляет все время процессора.

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

Ответ 3

Я считаю, что подсчет времени настенных часов, поэтому, если другие процессы прерывают GC и работают некоторое время, тогда это будет неправильно сообщено.

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

Управление очередями и запуск финализаторов могут занимать значительное количество времени, но не должны (??) подсчитываться по отношению к этому числу.

http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html содержит советы по настройке GC.

Ответ 4

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

Когда компилятор компилируется, компиляторы генерируют и сохраняют информацию о том, где ссылки на объекты живут (это помогает GC и называется oop map). Методы, превышающие определенный размер, не будут JIT-in точка доступа.... Если метод не был JIT'ed, GC должен генерировать собственные карты OOP во время GC.... Большие методы означают большие времена абстрактной интерпретации для генерации oop-карт..... Кстати, огромный метод был чем-то вроде 2500 строк, так что это было то, что я назвал бы огромным.

(Текст выделен полужирным шрифтом)