Когда именно JVM бросает OutOfMemoryError
Мы запускаем приложение Java, которое иногда "зависает", потому что какой-то поток использует почти всю кучу.
Несмотря на то, что JVM делает Full GC, который длится более 60 секунд, приложение никогда не умирает с OutOfMemoryError.
Я прочитал из документации Java, что:
Пропускной коллектор выкинет исключение из памяти, если слишком много времени тратится на сборку мусора. Например, если JVM тратит более 98% общего времени на сборку мусора и восстанавливает менее 2% кучи, он выкидывает изъятие из памяти.
Я хотел бы получить дополнительную информацию о том, что означает это 98% времени (каков временной интервал?), и если можно снизить это значение, то есть выбросить OOME, если приложение тратит 90% времени в GC и не может освободить более 10% кучи.
Цель состоит в том, чтобы убедиться, что приложение умрет (вместо выполнения только GC) с OOME, чтобы мы могли создать дамп на OOME.
Вот настройки памяти и GC, которые мы используем (ОС - Solaris):
-Xms2048m -Xmx2048m \
-Xmn512m \
-XX:PermSize=256m
-XX:MaxPermSize=256m \
-XX:+UseParNewGC
-XX:ParallelGCThreads=16 \
-XX:+UseConcMarkSweepGC
-XX:+CMSParallelRemarkEnabled \
-XX:+DisableExplicitGC \
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps \
-XX:+PrintClassHistogram \
-Xloggc:/gcmonitor.log \
-XX:+HandlePromotionFailure \
-XX:SurvivorRatio=4
-XX:TargetSurvivorRatio=90
-XX:MaxTenuringThreshold=10 \
-XX:+UseTLAB
-XX:TLABSize=32k
-XX:+ResizeTLAB \
-XX:+UseMPSS \
Ответы
Ответ 1
Я хотел бы получить дополнительную информацию о том, что означает это 98% времени (каков временной интервал?)
Отвечайте на этот вопрос: превышен лимит перегрузки GC. Это означает, что это 1 минута.
можно уменьшить это значение
Вновь рассмотрев упомянутый выше вопрос, вы можете использовать параметры GCTimeLimit
и GCHeapFreeLimit
.
Ответ 2
Если вы только хотите заставить OOM получить дополнительное преимущество кучи кучи, вы можете сделать это в текущем java-процессе в любое время:
Найдите процесс:
jps -v
Принудительный сброс
jmap -dump: file = heap.bin
Затем проанализируйте heap.bin в выбранном вами инструменте.
Ответ 3
Взятие кучи в интерактивном режиме на OOME или с помощью jmap может привести к остановке JVM в течение нескольких минут. Как правило, более эффективно использовать gcore для создания дампа ядра вручную, а затем использовать jmap, чтобы взять кучу кучи из ядра.
Я бы выделил больше кучи, посмотрим, поможет ли это решить проблему. Также будьте осторожны с чрезмерной настройкой GC - обычно у сборщиков отличные значения по умолчанию, я бы рекомендовал только варианты после Xloggc, если вы определили, что они значительно улучшают производительность GC на основе ваших шаблонов размещения/хранения приложений. Потоки параллельных коллекторов также могут быть слишком высокими, в зависимости от количества доступных аппаратных потоков.
Вы должны иметь возможность определить шаблон использования кучи из журналов GC и определить, является ли это быстрым использованием одним потоком, выполняющим операцию, которая быстро исчерпывает кучу, или более медленный шаблон "утечки", где многие объекты повышаются с течением времени, заставляя поколение поколений претендовать на участие, с несколькими кандидатами на объекты для сбора - гистограммы также помогут.
Все, что сказал, сосредоточившись на дампе кучи, определенно - путь. Eclipse MAT - лучший инструмент анализа IMO. Здесь отличное место для начала, если вы еще не использовали его раньше:
http://kohlerm.blogspot.com/2009/07/eclipse-memory-analyzer-10-useful.html