100% полное пространство Eden, 0% использовано Survivor space - сбор мусора не сделан - программирование

100% полное пространство Eden, 0% использовано Survivor space - сбор мусора не сделан

Я столкнулся с довольно запутанным случаем GC: в то время как пространство Эдена заполнено на 100%, используется 0% оставшегося в живых. Когда Иден заполнен, сбор мусора должен быть запущен, верно?

Может ли быть случай, когда демон GC не может быть запущен? Как 100% процессор?

Мы используем jdk-1.7.

В чем может быть причина? Ниже представлен вывод jmap.

Мы также попытались записать более детальное использование памяти с помощью jmap -histo -F, но затем загрузка процессора снизилась до 0%, а процесс java стал недоступен.

using thread-local object allocation.
Parallel GC with 18 thread(s)

Heap Configuration:
   MinHeapFreeRatio = 40
   MaxHeapFreeRatio = 70
   MaxHeapSize      = 12884901888 (12288.0MB)
   NewSize          = 1310720 (1.25MB)
   MaxNewSize       = 17592186044415 MB
   OldSize          = 5439488 (5.1875MB)
   NewRatio         = 2
   SurvivorRatio    = 8
   PermSize         = 21757952 (20.75MB)
   MaxPermSize      = 85983232 (82.0MB)
   G1HeapRegionSize = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 4265738240 (4068.125MB)
   used     = 4265738240 (4068.125MB)
   free     = 0 (0.0MB)
   100.0% used
From Space:
   capacity = 14352384 (13.6875MB)
   used     = 0 (0.0MB)
   free     = 14352384 (13.6875MB)
   0.0% used
To Space:
   capacity = 14680064 (14.0MB)
   used     = 0 (0.0MB)
   free     = 14680064 (14.0MB)
   0.0% used
PS Old Generation
   capacity = 8589934592 (8192.0MB)
   used     = 8589931920 (8191.997451782227MB)
   free     = 2672 (0.0025482177734375MB)
   99.99996889382601% used
PS Perm Generation
   capacity = 41353216 (39.4375MB)
   used     = 41079056 (39.17604064941406MB)
   free     = 274160 (0.2614593505859375MB)
   99.33702858805468% used
4b9b3361

Ответ 1

Когда я вижу в вашей конфигурации кучи, я обнаружил, что

MaxNewSize = 17592186044415 MB неверен, однако он должен быть в байтах.

Что я вижу, что почти все поколения полны и одинаковы, а Collector пытается собрать оба поколения, чтобы они блокировали друг друга.

Я предлагаю настроить мелодию памяти ниже.

-XX:NewRatio=3 - the young generation will occupy 1/4 the overall heap
-XX:NewSize - Calculated automatically if you specify -XX:NewRatio
-XX:MaxNewSize - The largest size the young generation can grow to (unlimited if this value is not specified at command line)

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

-XX:SurvivorRatio=6 - each survivor space will be 1/8 the young generation

Если оставшиеся в живых пространства слишком малы, копирование коллекции переполняется непосредственно в поколение.

Для любого пояснения обратитесь к этой ссылке.

Edit:

-XX:NewRatio=3 - молодое поколение займет 1/4 общей кучи

Расчет:

    y/t=1/3

    y+t=h
    y+3y=h
    y=h/4

 t=tenured
 y=young
 h=heap

Ответ 2

Локальные буферы потока выделяются из пространства eden. Как только выделен буфер, свободное пространство в пространстве эденов полностью уменьшается. Это может означать, что у вас много TLAB, которые почти пусты, но пространство eden кажется полным. GC запускается, когда свободного пространства в пространстве eden недостаточно.

Если вы отключите TLAB -XX:-UseTLAB, это замедлит работу, но вы получите точный отчет о том, как пространство используется.

Ответ 3

Просто мысль, но я вижу, что старый генерал тоже полон. Может быть, GC вместо того, чтобы пытаться очистить Eden, занят полным запуском GC, пытаясь очистить Old Generation, чтобы избежать OOM.

Ответ 4

Вывод SurvivorRatio:

Если SurvivorRatio = 6, то отношение (One SurvivorSpace: Eden) = (1: 6).
Итак, выйдут два оставшихся в живых (2 части), а у Идена 6 частей. Итак, всего 8 частей.
Итак, если у меня есть молодой ген 40 МБ, Eden (6/8 * 40) МБ, а у одного оставшегося в живых будет (1/8 * 40) МБ.

Если SurvivorRatio = 7. Тогда общие части (7 + 1 + 1 = 9). Eden (7/9 * 40) MB и выживший будет иметь (1/9 * 40) МБ

Теоретически

    The SurvivorRatio parameter controls the size of the two survivor spaces.
 For example, -XX:SurvivorRatio=6 sets the ratio between each survivor space 
and eden to be 1:6, each survivor space will be one eighth of the young 
generation.

Mathamatically

S - Оставшийся в живых
E - Eden
Y - Молодое поколение

if SurvivorRatio=6
then S / E = 1/6
         E = 6S

2S + E = Y
2S + 6S = Y
S = Y / 8

Эффект

Если увеличение до значения SurvivorRatio приводит к меньшему пространству для результатов Survivor, то нажатие объектов пространства eden непосредственно в старый/теневой ген. Малая возможность для фильтрации живых объектов на Survivor Space через небольшой GC. Также это может увеличить отсутствие полного GC.

Если уменьшить это до более низкого значения, это приведет к меньшему пространству с эденом, что сделает небольшой младший GC.

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

Также обратите внимание, что -XX:+UseAdaptiveSizePolicy будет определять JVM собственный SurvivorRatio во время выполнения, но всегда лучше упомянуть его вручную на основе вашего приложения, попробовав многократную загрузку.