Ответ 1
Я переключился с -Xmx1024m
на -Xmx2048m
, и проблема исчезла. У меня теперь есть 100 дней безотказной работы.
У меня есть Java webapp, работающий на одном экземпляре tomcat. Во время пиков webapp обслуживает около 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 начинает встречаться чаще, и это становится серьезной проблемой для доступности приложения. После перезапуска tomcat проблема исчезает, но, конечно, возвращается через 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
, когда появляются полные GC (я не уверен, правильно ли я их получил, когда был получен полный GC или между 2 полными GC) и открыл их в http://www.eclipse.org/mat/, но не получил ничего полезного для подозреваемых в утечке:
Обратите внимание, что я никогда не получаю OutOfMemoryError.
Любые идеи о том, где я должен смотреть дальше?
Я переключился с -Xmx1024m
на -Xmx2048m
, и проблема исчезла. У меня теперь есть 100 дней безотказной работы.
Когда у нас была эта проблема, мы в конечном итоге отследили ее до слишком маленького молодого поколения. Хотя мы дали много бара, молодому поколению не была предоставлена справедливая доля.
Это означало, что небольшие сборки мусора случались бы чаще и приводили к тому, что некоторые молодые объекты были перемещены в поколение, что означало бы более крупные коллекции мусора.
Попробуйте использовать -XX:NewRatio
с довольно низким значением (скажем, 2 или 3) и посмотрите, помогает ли это.
Более подробную информацию можно найти здесь.
Что может произойти в вашем случае, так это то, что у вас много объектов, которые живут немного дольше, чем жизненный цикл NewGen. Если пространство для оставшихся в живых слишком мало, они идут прямо к OldGen. -XX:+PrintTenuringDistribution
может дать некоторое представление. Ваш NewGen достаточно велик, поэтому попробуйте уменьшить SurvivorRatio
.
также, jconsole, вероятно, предоставит более визуальное представление о том, что происходит с вашей памятью, попробуйте.
Помимо настройки различных опций JVM, я также предлагаю перейти на более новую версию VM, потому что в более поздних версиях есть намного лучше настроенный сборщик мусора (также не пробовав новый экспериментальный).
Кроме того, если это (частично) истинно, что назначение большего количества бара для JVM может увеличить время, необходимое для выполнения GC, есть точка компромисса между использованием всего 16 ГБ памяти и увеличением вашей памяти, поэтому вы можете попробовать удвоить все значения, чтобы начать
Xms1024m -Xmx2048m -XX: PermSize = 256 м -XX: MaxPermSize = 512 м
Привет
Массимо