Полный GC становится очень частым - PullRequest
12 голосов
/ 27 октября 2011

У меня запущено веб-приложение на Java на одном экземпляре tomcat. В часы пик веб-приложение обслуживает около 30 страниц в секунду и обычно около 15.

Моя среда:

O/S: SUSE Linux Enterprise Server 10 (x86_64)
RAM: 16GB

server: Tomcat 6.0.20
JVM: Java HotSpot(TM) 64-Bit Server VM 1.6.0_14
JVM options:
CATALINA_OPTS="-Xms512m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=256m
               -XX:+UseParallelGC
               -Djava.awt.headless=true
               -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps"
JAVA_OPTS="-server"

После нескольких дней безотказной работы Full GC начинает появляться чаще, и это становится серьезной проблемой для доступности приложения. После перезагрузки кота проблема исчезает, но, конечно, возвращается через 5–10 или 30 дней (не соответствует).

Полный журнал GC до и после перезапуска находится в http://pastebin.com/raw.php?i=4NtkNXmi

Показывает журнал перед перезапуском при времени безотказной работы 6,6 дней, когда приложение страдало, потому что Full GC требовалось 2,5 секунды и происходило каждые ~ 6 секунд.

Затем он показывает журнал сразу после перезапуска, где Full GC происходил только каждые 5-10 минут.

У меня есть два дампа, использующих jmap -dump:format=b,file=dump.hprof PID, когда встречаются полные сборщики мусора (я не уверен, правильно ли я их получил, когда происходил сборщик Full GC, или между 2 полными сборками мусора) и открыл их в http://www.eclipse.org/mat/, но не получил ничего полезного в Leak Suspect:

  • 60 МБ: 1 экземпляр «org.hibernate.impl.SessionFactoryImpl» (я использую hibernate с ehcache)
  • 80 МБ: 1024 экземпляра "org.apache.tomcat.util.threads.ThreadWithAttributes" (это, вероятно, 1024 рабочих tomcat)
  • 45 МБ: 37 экземпляров "net.sf.ehcache.store.compound.impl.MemoryOnlyStore" (это должны быть мои ~ 37 областей кэша в ehcache)

Обратите внимание, что я никогда не получаю OutOfMemoryError.

Есть идеи, где мне искать дальше?

Ответы [ 4 ]

7 голосов
/ 27 октября 2011

Когда у нас возникла эта проблема, мы в конце концов отследили ее до слишком маленького молодого поколения. Хотя мы дали много барана, молодому поколению не дали его справедливой доли.

Это означало, что небольшие сборки мусора происходили бы чаще, и некоторые молодые объекты перемещались в постоянное поколение, что также означало более крупные сборки мусора.

Попробуйте использовать -XX:NewRatio с довольно низким значением (скажем, 2 или 3) и посмотрите, поможет ли это.

Более подробную информацию можно найти здесь .

4 голосов
/ 26 октября 2012

Я переключился с -Xmx1024m на -Xmx2048m, и проблема исчезла. Теперь у меня 100 дней безотказной работы.

3 голосов
/ 27 октября 2011

В вашем случае может случиться так, что у вас есть множество объектов, которые живут немного дольше, чем жизненный цикл NewGen. Если место для выживших слишком мало, они идут прямо к OldGen. -XX:+PrintTenuringDistribution может дать некоторое представление. Ваш NewGen достаточно велик, поэтому попробуйте уменьшить SurvivorRatio.

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

3 голосов
/ 27 октября 2011

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

Кроме того, если (частично) верно, что назначение большего количества оперативной памяти для JVM может увеличить время, необходимое для выполнения GC, существует компромисс между использованием целых 16 ГБ памяти и увеличением использования памяти, поэтому вы можете попробовать дважды все значения, для начала

Xms1024m -Xmx2048m -XX: PermSize = 256 м -XX: MaxPermSize = 512 м

Привет

Massimo

...