Я пытался исследовать java.lang.OutOfMemoryError: GC limit exceeded
, которое происходит при высокой нагрузке нашего веб-приложения, размещенного в котом. Размер кучи был установлен в 8 ГБ (-Xms2048m -Xmx8192m
)затмение анализатор памяти видит небольшую часть (363,2MB) всей кучи отвала (8GB)
В какой-то момент наше приложение перестает реагировать из-за накладных расходов GC. В журналах я видел, что Full GC происходит несколько раз подряд. Поэтому я взял кучу кучи со следующей командой (jmap -F -dump:format=b,file=/root/dump2.hprof 4963
). Файл, содержащий дамп, имел размер 9 ГБ. После сброса дампа (приложение замораживалось около 45 минут), несколько полных ГК происходили до того, как был выброшен OutOfMemoryError
.
Вот пример журнала ГК активности
[Full GC [PSYoungGen: 932096K->875513K(1864128K)] [ParOldGen: 5592447K->5592447K(5592448K)] 6524543K->6467961K(7456576K) [PSPermGen: 112285K->112285K(262144K)], 12.3954040 secs] [Times: user=47.60 sys=0.43, real=12.39 secs]
[Full GC [PSYoungGen: 932096K->890562K(1864128K)] [ParOldGen: 5592447K->5592447K(5592448K)] 6524543K->6483009K(7456576K) [PSPermGen: 112285K->112285K(262144K)], 12.6131900 secs] [Times: user=48.45 sys=0.49, real=12.61 secs]
[Full GC [PSYoungGen: 932096K->895268K(1864128K)] [ParOldGen: 5592447K->5592447K(5592448K)] 6524543K->6487715K(7456576K) [PSPermGen: 112285K->112285K(262144K)], 12.9488670 secs] [Times: user=49.61 sys=0.46, real=12.95 secs]
Heap
PSYoungGen total 1864128K, used 896698K [0x0000000755560000, 0x0000000800000000, 0x0000000800000000)
eden space 932096K, 96% used [0x0000000755560000,0x000000078c10e8a8,0x000000078e3a0000)
from space 932032K, 0% used [0x000000078e3a0000,0x000000078e3a0000,0x00000007c71d0000)
to space 932032K, 0% used [0x00000007c71d0000,0x00000007c71d0000,0x0000000800000000)
ParOldGen total 5592448K, used 5592447K [0x0000000600000000, 0x0000000755560000, 0x0000000755560000)
object space 5592448K, 99% used [0x0000000600000000,0x000000075555ff30,0x0000000755560000)
PSPermGen total 262144K, used 112285K [0x00000005e0000000, 0x00000005f0000000, 0x0000000600000000)
object space 262144K, 42% used [0x00000005e0000000,0x00000005e6da7530,0x00000005f0000000)
heap dump is taken (ca 45minutes freeze)
[Full GC [PSYoungGen: 932096K->903362K(1864128K)] [ParOldGen: 5592447K->5592447K(5592448K)] 6524543K->6495810K(7456576K) [PSPermGen: 112285K->112285K(262144K)], 2883.9864390 secs] [Times: user=49.41 sys=0.47, real=2884.17 secs]
[Full GC [PSYoungGen: 932096K->897728K(1864128K)] [ParOldGen: 5592447K->5592444K(5592448K)] 6524543K->6490173K(7456576K) [PSPermGen: 112288K->112288K(262144K)], 13.3092680 secs] [Times: user=50.75 sys=0.40, real=13.31 secs]
Для анализа дампа кучи я открыл ее в затмении анализатора памяти (MAT). К сожалению, MAT показывает, что размер кучи составил 363,2 МБ (на вкладке «Обзор» или вкладке «Сведения о кучи»), тогда как в соответствии с GC-журналами куча была заполнена до 6467961K (6.4G). Недостижимые объекты Гистограмма показывает в общей сложности 75 511 736 (75 МБ). Гистограмма также подтвердила, что общая неглубокая куча была 380 837 136 (363,2 МБ)
Мой вопрос: почему MAT не отображает все объекты из дампа кучи, если GC не может вернуть память?
env details:
Eclipse Memory Analyzer Version 1.2.1
heap dump taken on
java version "1.7.0_13"
Java(TM) SE Runtime Environment (build 1.7.0_13-b20)
Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode)
Вот скриншоты импортного дампа кучи в МХТ:
Я столкнулся с ситуацией, когда мы использовали выше флаг -XX: + HeapDumpOnOutOfMemoryError для создания дампа кучи, и он не сгенерировал кучу кучи, когда мы столкнулись с java.lang.OutOfMemoryError: предел GC превысил проблему, так как продолжает вызовы GC вызвало освобождение памяти, и оно запустило использование ЦП на более высокий уровень, и сервер не ответил, поэтому сервер сработал до запуска кучи кучи. пришлось использовать утилиту jmap и получить дамп кучи, когда использование памяти превышает 98%, что на самом деле не дало нам получить точный снимок во время OOM –