Углубленный анализ принципа реализации сборщика мусора G1

задняя часть JVM

1 Алгоритмы, связанные со сборщиками мусора

Прежде чем анализировать G1, кратко рассмотрим алгоритмы, связанные со сборщиком мусора. Обычно то, что называется сборщиком мусора, больше похоже на отслеживающий сборщик мусора (Tracing Garbage Collection), а не подсчет ссылок (Reference Counting) уборщик мусора. Отслеживающий сборщик мусора использует метод анализа достижимости, чтобы определить, какие объекты должны быть утилизированы, и обычно выбирает некоторые объекты в качестве корней GC.Если на объект могут прямо или косвенно ссылаться объекты в корнях GC, объект считается достижимым ( выжившие объекты). ) не могут быть утилизированы, в противном случае объект недостижим (мусорный объект) для утилизации.

1.1 Алгоритм трехцветной маркировки

​ При определении того, какие объекты в памяти являются мусорными объектами, можно использовать простейший алгоритм маркировки, то есть присвоение каждому объекту в памяти специального бита маркировки, и он считается уцелевшим, если он помечен, в противном случае он является мусорным объектом, а затем GC Roots. Набор объектов начинает рекурсивно перемещаться по графу объектов и отмечает, могут ли объекты в графе объектов напрямую или просто ссылаться на объекты в GC Roots. Алгоритм теоретически может определить, какие объекты в памяти живые, а какие мусорные, но весь процесс приложение должно приостановить и обработать все области памяти.

Чтобы решить вышеуказанные проблемы, Dijkstra et al.On-the-Fly Garbage Collection: An Exercise in CooperationТрехцветный маркер (Tri-color Marking)алгоритм. Такие языки, как Go, JavaScript, Java и т. д., используют варианты алгоритма трехцветной маркировки для освобождения памяти.

** Алгоритм трехцветной маркировки создает три набора белого, серого и черного цветов, и в этих трех наборах сохраняются только белые, серые и черные объекты. Белые объекты представляют объекты, которые еще не начали маркировку или объекты, которые были помечены и подтверждены как мусор; серые множества представляют объекты, которые все еще отмечены, то есть они прошли себя при обходе графа объектов, но не завершили обход своих собственных объектов, на которые ссылаются; Черный объект представляет собой объект, который был помечен и подтвержден как живой (при нормальных обстоятельствах изменение цвета маркировки объекта может меняться только с белого на серый и с серого на черный). Вначале черный набор обычно пуст, объекты, на которые непосредственно ссылается GC Roots, находятся в сером наборе, а остальные объекты — в белом наборе. Объект может быть только в одном из трех наборов белого, серого и черного в любой момент времени. **Обычно процесс обработки алгоритма трехцветной маркировки выглядит следующим образом:

1. Сначала все объекты, кроме GC Roots, задаются белым цветом, а объекты, на которые непосредственно ссылается GC Roots, перемещаются из белого набора в серый набор.

2. Выньте серый объект из набора серых и по очереди обработайте объекты, на которые ссылается этот объект. Если он не ссылается ни на какой объект, переместите его прямо в черный набор; если объект, на который он ссылается, находится в белом наборе, переместите его в серый набор, иначе он не будет обрабатываться напрямую, когда все объекты, на которые ссылается набор серый объект обрабатывается, затем переместите его в черный набор.

3. Повторяйте шаг 2, пока серый набор не станет пустым.

4. После выполнения вышеуказанных шагов GC Roots и объекты в черном наборе являются уцелевшими объектами, а объекты в белом наборе - мусорными объектами.Последнее, что нужно сделать, это очистить мусорные объекты в белом наборе .

На следующем рисунке показан поток обработки алгоритма трехцветной маркировки при наличии 8 объектов в дополнение к корням GC.

  • Сначала, за исключением объектов в GC Roots, все остальные объекты находятся в белой коллекции справа.

  • После того, как объекты, на которые непосредственно ссылается GC Roots, перемещены из белого набора в серый набор, объекты A и F были перемещены из белого набора в серый набор.

  • После обработки объекта B, на который ссылается объект A в сером наборе, объект B был перемещен из белого набора в серый набор.

  • После обработки объекта C и объекта D, на который ссылается объект A в сером наборе. В этот момент объект A переместился из серого набора в черный набор, а объекты C и D переместились из белого набора в серый набор.

  • После обработки оставшихся объектов B, C, D и F из серого набора объекты B, C, D и F были перемещены из серого набора в черный.

  • После вышеуказанной обработки серый набор пуст, метод трехцветной маркировки завершен и достигнут этап очистки, а объекты E, G и H в белом наборе очищаются. Конечный результат выглядит так, как показано на рисунке. ниже.

1.2 Недостатки алгоритма трехцветной маркировки

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

Возьмите приведенный выше пример, чтобы увидеть, как происходит пропуск.

Предполагая, что поток GC готов пометить следующий шаг, состояние пометки объекта будет таким, как показано выше. В это время следующим шагом потока GC будет обработка объекта F в сером наборе. Поскольку объект F не ссылается ни на один объект, он будет непосредственно перемещен в черный набор, а весь серый набор пуст. Отметьте конец.Но что, если поток приложения просто увеличивает ссылку F-объекта на G-объект, когда поток GC не завершил передачу F-объекта из серого множества в черное множество?

Поскольку F-объект завершил работу по маркировке (фактический поток GC считал F-объект черным), F-объект в конечном итоге будет успешно перенесен из серого набора в черный. Поток GC не сможет воспринять приложением ссылку вновь добавленного F-объекта на G-объект, что в конечном итоге приведет к отсутствию G-объекта. На самом деле наличие отсутствующих меток должно удовлетворять одному из следующих двух условий.

1. В процессе маркировки потока GC поток приложения увеличивает ссылку черного объекта на белый объект.

2. В процессе маркировки потока GC поток приложения удаляет ссылку серого объекта на белый объект.

Приведенный выше пример отсутствия этикеток на самом деле является первым случаем, бумагаUniprocessor Garbage Collection TechniquesВ подразделе 3.2.1 Инкрементный подход GC разделяется на сборщики моментальных снимков в начале и сборщики инкрементных обновлений с различными проблемами при работе с отсутствующими метками. Сборщики моментальных снимков в начале сосредоточены на обработке первого случая, в то время как сборщики добавочных обновлений фокусируются на обработке второго случая, G1 — это сборщики моментальных снимков в начале, а CMS — сборщики добавочных обновлений. Параллельный процесс маркировки G1 фокусируется на обработке потоков приложений для добавления ссылок от черных объектов к белым объектам, то есть, когда черный объект вновь ссылается на белый объект, черный объект сбрасывается до серого (технически используется барьер предварительной записи). ); в то время как CMS Процесс маркировки связан с тем, что поток обработки удаляет ссылку серого объекта на белый объект, то есть, когда серый объект удаляет ссылку на белый объект, белый объект сразу становится серым (технически, используется барьер после записи).

Какие технические средства используются для решения двух вышеуказанных ситуаций? На самом деле это тоже очень просто: нужно найти способ сделать так, чтобы поток GC знал об изменениях в ссылках на объекты, так называемый барьер записи. Упомянутый здесь барьер записи — это не барьер записи на аппаратном уровне, а барьер записи на программном уровне, его суть можно понять как добавление фасета перед операцией записи присваивания ссылки, которую можно разделить на пре-барьер записи и барьер после записи, ниже приведена реализация псевдокода барьера записи, используемого в G1 (От [HotSpot VM] Спросите принцип алгоритма G1).

void oop_field_store(oop* field, oop new_value) {
  pre_write_barrier(field);             // pre-write barrier: for maintaining SATB invariant
  *field = new_value;                   // the actual store
  post_write_barrier(field, new_value); // post-write barrier: for tracking cross-region reference
}

В G1 барьер предварительной записи используется для обеспечения целостности SATB (моментального снимка в начале), который должен обрабатываться в параллельном процессе маркировки (реализация G1 SATB будет подробно проанализирована позже), т. е. , поток GC находится в начальной стадии отслеживающей маркировки. Когда создается моментальный снимок графа объектов, модификация моментального снимка графа объектов потоком приложения может восприниматься через барьер предварительной записи. С другой стороны, G1 использует барьер после записи для поддержки перекрестных ссылок, которые необходимо отслеживать, вновь сгенерированные потоком приложения во время параллельного процесса маркировки (это будет объяснено позже при анализе RSet G1).

1.3 Как реализовать очистку объекта

Когда объект отмечен, объект может быть очищен. В конкретной реализации есть три способа пометить алгоритм очистки, пометить копирование, пометить алгоритм сжатия. Очистка меток является самой простой и эффективной, она напрямую очищает эти мусорные объекты, но это также приводит к проблеме фрагментации памяти, и в то же время для выделения объектов приходится использовать алгоритм списка свободного места вместо эффективного указателя. алгоритм столкновения. Алгоритм копирования пометки обычно занимает дополнительно 50% пространства. Реализация заключается в том, чтобы всегда использовать половину памяти для хранения объектов, а другая половина памяти пуста. Когда мусор собирается, объекты все еще живы в используемом пространство копируется непосредственно в пустой сегмент памяти, а затем сразу очищается половина памяти, использованная ранее. Алгоритм сжатия меток учитывает преимущества алгоритмов очистки меток и алгоритмов копирования меток.После сборки мусора уцелевшие объекты будут перемещены соответствующим образом, а фрагментированное пространство памяти будет максимально сжато.

Сборщик мусора 2-го поколения

Прежде чем анализировать сборщик мусора G1, необходимо кратко рассмотреть другие сборщики мусора в виртуальной машине HotSpot. До появления G1 другие сборщики мусора в виртуальной машине HotSpot основывались на молодом поколении и старом поколении для сборки мусора.Эти наборы сборщиков мусора в совокупности называются мусором поколений. G1 — это сборщик мусора, который учитывает как генерацию, так и разбиение.

2.1 Процесс сборки мусора сборщиком мусора поколений

Генерационный сборщик мусора делит кучу на Young Generation и Old Generation.До JDK1.8 также существовала концепция постоянного поколения. Новое поколение далее делится на Eden, From Space, To Space, из которых From Space и To Space равны по размеру, также известные как Survivor Spaces.

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

1. На большинство выделенных объектов не ссылаются в течение длительного времени (считаются живыми), т.е. они умирают молодыми.

2. Старые объекты редко содержат ссылки из новых объектов.

Сборка мусора молодого поколения выполняется относительно часто, а используемый алгоритм эффективен и быстр, поскольку пространство молодого поколения обычно невелико и может содержать много объектов, на которые больше нет ссылок. Частота сборки мусора старого поколения относительно низкая, но поскольку старое поколение занимает относительно больше памяти, обычно сборка мусора старого поколения занимает больше времени. Новое поколение и старое поколение хранят объекты разного возраста соответственно.Обычно в новом поколении хранятся объекты, которым только что была выделена память.После каждой сборки мусора, если объект все еще выживает, его возраст увеличивается на 1. После многократного циклы сборки мусора, если возраст объекта равен Если возраст превышает значение MaxTenuringThreshold, объект будет переведен в старое поколение.

Поскольку сборка мусора нового поколения выполняется относительно чаще, сборка мусора нового поколения уделяет больше внимания своевременности сборки мусора и обычно использует алгоритм репликации или алгоритм пометки и очистки для обработки сборки мусора. Старое поколение занимает относительно больше памяти, а сборка мусора происходит реже.Сборка мусора старого поколения уделяет больше внимания пространственности сборки мусора, то есть может ли быть освобождено больше непрерывной памяти после сборки мусора.Обычно алгоритм сжатия используется для обработки сборки мусора.

Теперь давайте кратко рассмотрим, как объекты распределяются и передаются между Eden, Survivor и Old Generation.

  • Любые новые объекты выделяются в пространство Эдема молодого поколения.Когда область Эдема не может вместить новые объекты, срабатывает Молодой GC. В начале две ячейки Выживших пусты (на рисунке ниже показана ситуация после нескольких ГК).

  • Объекты (выжившие объекты), на которые все еще ссылаются в пространстве Eden во время процесса Young GC, будут скопированы в первое пространство Survivor (S0 Survivor Space). Объекты, на которые нет ссылок в пространстве Эдема, будут удалены напрямую. Возраст объектов, выживших после GC Young, увеличится на 1. Объекты в Пространстве Survivor S0 на следующем рисунке испытали только GC Young и отмечены цифрой 1.

  • Объекты, на которые все еще ссылаются (выжившие объекты) в следующем Young GC, будут скопированы в ранее пустое пространство оставшихся в живых (в пространство оставшихся в живых, фактически предыдущее пространство оставшихся в живых S1), а неиспользуемые объекты в пространстве Эдема будут удалены напрямую. Бывшее пространство оставшихся в живых S0 теперь называется пространством оставшихся в живых форм, в котором объекты, на которые ссылаются, воспроизводятся в ранее пустое пространство оставшихся в живых (в пространство оставшихся в живых), а объекты, на которые нет ссылок в пространстве оставшихся в живых, будут удалены напрямую. После того, как объект, на который все еще ссылаются, скопирован из пространства оставшихся в живых в форме в пространство до оставшихся в живых, его возраст объекта будет увеличен на 1, указывая на то, что объект подвергся еще одному молодому GC.

  • В следующем Young GC будет повторяться тот же процесс, что и выше. Тем не менее, роли в пространстве выживших в это время поменяются, то есть из пространства выжившего станет в пространство выжившего, а в пространство выжившего станет из пространства выжившего. Цель этого обмена состоит в том, чтобы скопировать уцелевшие объекты из использованной ячейки Выжившего в пустую ячейку Выжившего.

  • ** Объекты, которые все еще живы в молодом поколении после многократного юного GC, будут переведены в старое поколение. На следующем рисунке показано, что когда параметр MaxTenuringThreshold равен 8, уцелевшие объекты перемещаются из молодого поколения из оставшегося пространства в старое поколение. **

  • При постоянном появлении Young GC объекты, все еще живые в молодом поколении, будут постоянно продвигаться к старому поколению. В конце концов, в старом поколении не останется места для размещения вновь продвинутых объектов, что приведет к запуску основного GC.

Подробную блок-схему того, когда GC будет запускаться во время выделения и продвижения объектов, см. на следующем рисунке (см. рисунок в главе 4 «Эффективность кода: руководство по разработке Java» при входе в JVM):

На приведенном выше рисунке не показаны детали локального буфера распределения потока (TLAB) и буфера локального распределения продвижения (PLAB). Кроме того, полный сборщик мусора на приведенном выше рисунке может вызвать двусмысленность, поскольку его слишком легко спутать с основным сборщиком мусора. Фактическая спецификация JVM и литература по сборке мусора не определяют Full GC и Major GC. Как правило, полная сборка мусора считается сборкой мусора как для молодого поколения, так и для старого поколения, в то время как основная сборка мусора предназначена специально для сборки мусора старого поколения. Вопрос в том, что Young GC запускает сборку мусора в старости, следует ли его называть Full GC или Major GC? Лично я думаю, что Full GC может быть более подходящим, и вам не нужно слишком беспокоиться об этом. Чтобы добиться запутанности, вы можете посмотреть эти две статьиMinor GC vs Major GC vs Full GCиВ чем разница между Major GC и Full GC? А как насчет триггерных условий?.

Выше приведено лишь краткое описание процесса сборки мусора сборщиком мусора поколений, собственно сборщик мусора отвечает не только за восстановление памяти, но и за выделение объектов. Дополнительные вводные материалы см.Управление памятью в виртуальной машине Java HotSpot™,Plumbr Handbook Java Garbage Collection. Если вы хотите узнать больше о сборке мусора, вы также можете ознакомиться с «Справочником по алгоритмам сборки мусора. Искусство автоматического управления памятью».

2.2 Последовательный сборщик мусора

Последовательный сборщик мусора (Serial GC) имеет только один поток GC для сборки мусора во время сборки мусора. Обычно проще реализовать последовательный сборщик мусора, и нет необходимости поддерживать сложные структуры данных внутри последовательного сборщика мусора, а накладные расходы памяти также меньше. Однако, поскольку во время STW (Stop The World) работу по сборке мусора выполняет только один поток GC, время сборки мусора обычно велико и линейно увеличивается с объемом памяти, занимаемой приложением. Этот сборщик мусора больше подходит для сценариев, занимающих меньше памяти, таких как клиенты и встроенные устройства.

​Серая стрелка на картинке выше — это поток приложения, а черная стрелка — это поток GC. Поток приложения при работе обычно является многопоточным, и поток приложения перестает работать после достижения безопасной точки. Это также называется SWT (Stop The World), последовательная сборка мусора. Процессор запустит поток GC для завершения работы по сборке мусора. Серийные сборщики мусора обычно делятся на серийные новые и серийные старые в соответствии с разными поколениями коллекций, и они отвечают за переработку молодого поколения и старого поколения соответственно. Serial New использует алгоритм репликации для очистки от мусора, а Serial Old использует алгоритм сжатия для очистки от мусора.

2.3 Параллельные сборщики мусора

Очевидно, что последовательный сборщик мусора не может использовать преимущества многоядерного ЦП, когда сборка мусора выполняется в многоядерной архитектуре ЦП. Поэтому используется параллельный сборщик мусора (Parallel GC), самое большое отличие которого от последовательного сборщика мусора состоит в том, что в STW поток для сборки мусора меняется с одиночного на множественный. По сравнению с последовательным сборщиком мусора, поскольку работа по сбору мусора распределяется между несколькими потоками, общее время будет значительно сокращаться при каждом выполнении сборщика мусора. Когда работает параллельный сборщик мусора, и молодое поколение, и старое поколение используют потоки для параллельной обработки работы по сборке мусора. Как и последовательный сборщик мусора, параллельный сборщик мусора обычно делится на ParNew и Parallel Old в соответствии с разными поколениями коллекций, которые отвечают за переработку молодого поколения и старого поколения соответственно. Точно так же сборка мусора нового поколения использует алгоритм репликации для завершения работы по очистке от мусора, а старое поколение использует алгоритм сжатия для завершения работы по очистке от мусора.

Серые стрелки на приведенном выше рисунке — это потоки приложения, а черные стрелки — это потоки GC.Потоки, которые параллельный сборщик мусора выполняет сборку мусора во время STW, становятся несколькими потоками по сравнению с последовательным сборщиком мусора, и эти потоки одновременно выполняют сборку мусора. Работы по переработке.

2.4 Параллельный сборщик мусора с маркировкой и очисткой

Concurrent Mark Sweep (CMS) — это настоящий параллельный сборщик мусора на виртуальной машине Hotspot. Так называемый параллельный (Concurrent) означает, что поток GC и поток приложения работают вместе.Поток GC не нуждается в STW при работе, и поток приложения также работает, тогда как параллельный (Parallel) обычно означает, что несколько потоков GC работать в то же время, чтобы убрать мусор. Потоки приложений во многих источниках называются потоками-мутаторами.

CMS в основном отвечает за переработку мусора старого поколения.При использовании CMS сбор мусора нового поколения обычно выполняется Serial New или ParNew.Сборщиком мусора нового поколения по умолчанию является ParNew. Когда CMS собирает мусор старого поколения, общий процесс сбора мусора делится на несколько этапов, и большинство этапов и потоков приложений являются параллельными, и STW не выполняется. Общий процесс сборки мусора CMS можно разделить на Начальную маркировку, Параллельную маркировку, Параллельную предварительную очистку, Ремарку, Параллельную очистку, STW происходит для всех маркировок, но обычно в течение относительно короткого периода времени. В более ранних версиях CMS маркировка и перемаркировка инициализации выполнялись одним потоком, в более поздних версиях фазы маркировки и перемаркировки инициализации можно указать как многопоточные с помощью -XX:+CMSParallelInitialMark и -XX:CMSParallelRemarkEnabled соответственно. Когда CMS выполняет параллельную сборку старого поколения, Young GC может происходить во многих молодых поколениях, в это время сборка мусора старого поколения будет немедленно прервана и возобновится после окончания Young GC.

Серые стрелки на приведенном выше рисунке — это потоки приложения, а черные стрелки — потоки GC.CMS запускает несколько потоков GC, чтобы пометить корень GC на этапе начальной маркировки, что обычно занимает короткое время. CMS начинает многопоточную работу на этапах параллельной маркировки и параллельной предварительной очистки, на этом этапе поток GC и поток приложения работают параллельно. Длинные черные стрелки на этапе предварительной очистки параллельного выполнения на приведенном выше рисунке обозначают потоки GC, которые обрабатывают работу параллельного создания, а короткие черные стрелки обозначают потоки, которые обрабатывают работу предварительной очистки. CMS также запускает несколько потоков GC во время перемаркировки и выполняет SWT, как на этапе начальной маркировки. Потоки CMS GC работают одновременно с потоками приложений на этапе параллельной очистки.

Ключевой вопрос настройки CMS заключается в том, как определить правильное время для CMS, чтобы начать параллельную работу, чтобы CMS завершила всю параллельную работу до того, как приложение исчерпает доступное пространство кучи. Обычно параллельная работа CMS начинается после Young GC, потому что после Young GC обычно меньше объектов, которые нужно пометить CMS Initail-mark. Другой проблемой CMS является проблема фрагментации памяти старого поколения.Поскольку CMS принимает алгоритм маркировки и очистки при восстановлении памяти старого поколения, алгоритм маркировки-очистки более эффективен, чем алгоритм сжатия, но поскольку контроль памяти отсутствует при очистке мусора.Сжатие дефрагментации, что неизбежно приводит к проблемам с фрагментацией памяти. Следующие две ситуации в конечном итоге приведут к сбою параллельного режима из-за фрагментации памяти.

1. Во время Young GC уцелевшие объекты в области Eden слишком велики и не могут быть сохранены в области Survivor, что приводит к сбою продвижения.В это время объект можно разместить только в старом поколении, но из-за памяти фрагментация, старое поколение тоже не может поставить объект, и в итоге произойдет concurrent.mode failure, тогда сработает Full GC, Full GC вернет себе все пространство Heap и вызовет резкое увеличение длительности STW.

2. Во время молодого GC возраст уцелевшего объекта в области Survivor превышает MaxTenuringThreshold и повышается до старого поколения.Однако из-за проблемы фрагментации памяти старое поколение не может удерживать объект, и сбой параллельного режима будет произойдет, что вызовет полный сборщик мусора.

Для получения дополнительной практики по настройке CMS вы можете обратиться к этим двум статьям.Анализ и решения 9 распространенных проблем CMS GC в JavaиUnderstanding GC pauses in JVM, HotSpot's CMS collector

Ниже представлена ​​классическая схема того, как сборщик мусора в HotSpot VM объединяет молодое и старое поколения. Serial New, ParNew и Parallel Scavenge в верхней части предназначены для работы со сборщиком мусора нового поколения, CMS, Serial Old и Parallel Old в нижней части — это сборщики мусора, предназначенные для работы со старым поколением, а G1 посередине Он может справиться как с молодым поколением, так и со старым поколением. Сплошные черные линии на рисунке показывают, какие сборщики мусора нового поколения могут работать в сочетании с какими сборщиками мусора старого поколения. Черная пунктирная линия между CMS и Serial Old указывает, что когда CMS дает сбой в параллельном режиме, он становится безопасным и становится полным GC.Serial Old используется для повторного использования мусора старого поколения.

​ Для Serial GC (Serial New и Serial Old), Parallel GC (ParNew, Parallel Scavenge, Parallel Old) и CMS, упомянутых выше, поскольку структура памяти нового поколения и старого поколения непрерывна (виртуальная память непрерывна). сборщики мусора могут обрабатывать только определенный раздел или всю кучу при сборе мусора. Это неизбежно приведет к более или менее линейной положительной корреляции между временем STW сборки мусора и памятью, занимаемой приложением, то есть чем больше памяти, занимаемой приложением, тем дольше будет время STW при выполнении сборки мусора . Все предыдущие сборщики мусора являются сборщиками мусора поколений.G1 открывает прецедент сборщиков мусора разделов (хотя G1 логически также имеет концепции нового поколения и старого поколения). G1 использует идею «разделяй и властвуй», чтобы разделить всю кучу на регионы одинакового размера, которыми можно управлять во время управления памятью, а не в генерации в целом. Поскольку размер региона обычно намного меньше, чем размер поколения, эффективность обработки нескольких регионов при сборке мусора обычно выше, чем обработка определенного поколения.

3 Обзор сборщика мусора G1

Сборщик мусора G1 (Garbage First) — это еще один сборщик мусора перекрестного поколения после сборщика CMS, который открыл прецедент сборщика мусора разделов. G1 использует модель прогнозирования времени, чтобы максимально удовлетворить требования пользователя к времени паузы (пользователь может указать максимальное время паузы во время сборки мусора с помощью -XX:MaxGCPauseMillis=XXX), а G1 использует алгоритм сжатия для оптимизации сбора мусора. Больше разделов, поэтому он называется Garbage First сборщик мусора.

3.1 Расположение памяти в сборке мусора G1

G1 имеет те же концепции Eden Generation, Survivor Generation и Old Generation, что и традиционные сборщики мусора поколений, представленные выше, но самая большая разница с ними заключается в том, что связь между этими поколениями логична, а структура памяти каждого поколения не изменится. , Существует преемственность. G1 делит кучу на регионы, размер каждого региона равен 2 в N-й степени, а его значение находится в диапазоне от 1M до 32M. Каждый Регион принадлежит определенному Поколению, поэтому есть понятия Район Эдема, Регион Выжившего, Старый Регион/Постоянный Регион (в отличие от традиционного сборщика мусора поколений, в G1 нет понятия From Survivor и To Survivor, потому что G1 не имеет значения объекты Young GC, Mix GC, Full GC переносятся из одного региона в другой или очищаются напрямую). Кроме того, G1 также имеет регион, предназначенный для хранения больших объектов (объект по умолчанию занимает более половины размера региона), который называется Humongous Region.Humongous Region может состоять из нескольких регионов, но один регион имеет наибольшее количество объектов. хранить большой объект, когда несколько регионов используются для хранения особенно большого объекта, эти регионы внутренне непрерывны в макете. После нескольких групп Young GC, Mix GC, Full GC и распределения объектов (вещи, связанные с Young GC, Mix GC и Full GC в G1, будут рассмотрены позже), роли между регионами Eden, Survivor Region, Old Region и Humongous Region It будет изменен, то есть Регион, в котором изначально хранился определенный объект Поколения, может быть использован для хранения одного из объектов Эдема, объектов Выживших, Старых объектов или Огромных объектов после опустошения.

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

3.2 Цикл сборки мусора G1

​ С глобальной точки зрения процесс сборки мусора сборщиком G1 чередуется между этапом «только для молодых» и этапом восстановления пространства.Следующий рисунок взят с официального сайта Oracle.HotSpot Virtual Machine Garbage Collection Tuning Guideв одной статье.

  • Только для молодых

    Этап только для молодых фактически включает в себя несколько GC для молодых и весь параллельный процесс оценки. Он начинается с некоторого нормального GC Young (маленькие синие точки на изображении выше представляют нормальный GC Young) и продвигает подходящие объекты к старому поколению. Когда объем памяти, занимаемой старым поколением, превысит пороговое значение, будет запущена фаза параллельной маркировки, пороговое значение задается параметром -XX:InitiatingHeapOccupancyPercent=65%, а заданное значение по умолчанию равно 65%. В то же время G1 запустит параллельный Young GC (большой синий значок на рисунке выше представляет параллельный Young GC) вместо обычного Young GC. Вся фаза параллельной маркировки чередуется с обычной GC Young. Фаза параллельной маркировки может быть дополнительно подразделена на фазы начальной маркировки, примечания и очистки. Начальная фаза маркировки фактически выполняется в параллельном GC Young (обычно упоминается в литературе как совмещение). Когда метка инициализации завершена, перед переходом на стадию Remark может произойти несколько обычных Yong GC (желтая точка вверху на рисунке выше). Затем параллельная маркировка может быть прервана GC Young, и фаза очистки начинается после GC Young (желтая точка внизу на рисунке выше).

  • Этап освоения космоса

    Когда Очистка завершится, G1 перейдет на этап «Освобождение пространства», который состоит из нескольких MixGC. Каждый MixGC выберет часть объектов, отмеченных на предыдущей фазе одновременной маркировки, для очистки, а процесс MixGC сопровождается частью Young GC (красная точка на приведенном выше рисунке представляет MixGC). Когда G1 обнаружит, что места, полученного в результате очистки объекта, недостаточно, он остановит MixGC, и в то же время закончится фаза освобождения пространства.

Когда фаза освоения пространства заканчивается, цикл сбора G1 снова начинается с фазы только для молодых. Условие срабатывания общего сборщика мусора Young GC в Young-only такое же, как и условие срабатывания сборщика мусора предыдущего поколения Young GC, за исключением того, что G1 обрабатывается для региона, то есть G1 будет основываться на наличии региона. в регионе Эдема, который может вместить новые объекты.Решите, следует ли включить Young GC. В качестве итоговой стратегии, когда памяти, освобождаемой процессом сборки мусора G1, недостаточно для удовлетворения требований к памяти для новых объектов в приложении, G1 будет использовать полный сборщик мусора для обработки всех регионов.

3.3 Набор памяти (RSet)

Как мы узнали ранее, Young GC обрабатывает только регионы, соответствующие новому поколению, а именно Eden Region и Survivor Region, что выгодно для сокращения времени каждого Young GC. Но если Eden Region и Survivor Region содержат ссылки на старую эру, нужно ли во время Young GC пройти все регионы в Heap один раз, чтобы определить, какие объекты в Eden Region и Survivor Region являются мусором? Этот метод явно не рекомендуется, так как это удлинит время Янга GC.

Эффективным методом является поддержание коллекции для каждого региона нового поколения для записи межпоколенческих ссылок точки входа, на которую указывает старое поколение, так что вам нужно будет только просматривать эту коллекцию точек во время Young GC.Этот набор является так называемым набором запоминания (RSet). Нужен ли этот RSet в старом поколении? Как упоминалось ранее, каждый Mix GC будет перерабатывать некоторые регионы в старом поколении.Если нет набора памяти, это то же самое, что и Young GC.Также неизбежно сканировать весь регион старого поколения, поэтому регион старому поколению также необходимо поддерживать точку -в наборе, но запись набора - это набор из точки входа Старого региона, что касается точки входа Молодого региона, вы можете его игнорировать.

Какова конкретная реализация RSet? Перед этим надо знать таблицу карточек (CardTable), а еще в CMS до G1 есть CardTable. CardTable — это, по сути, структура данных, указывающая на то, что сама область имеет ссылки на другие области. В G1 CardTable состоит из байтового массива, и каждый элемент массива называется картой/страницей карты (CardPage). CardTale будет отображать все пространство кучи, и каждая страница CardPage будет соответствовать 512 байтам пространства в куче. Как показано на рисунке ниже, в куче размером 8ГБ длина CardTable составляет 16777215 (8ГБ/512Б); при условии, что параметр -XX:G1HeapRegionSize равен 2МБ, то есть размер каждого Региона равен 2 МБ, то каждому региону будет соответствовать 4096 карточных страниц. CardTable займет 16 МБ дополнительного места в памяти.

Чтобы найти CardPage, на которой находится объект, просто примените следующую формулу.

CardPageIndex=(адрес объекта — начальный адрес кучи)÷512CardPageIndex = (адрес объекта - начало кучи) ÷ 512

​После разговора о CardTable, давайте посмотрим на конкретную реализацию RSet.RSet на самом деле реализован через HashMap.Ключ этого HashMap относится к адресу другого Regionr в этом Region.Значение представляет собой массив, а элементы массива соответствуют объекту ссылочной стороны Нижний индекс CardPage в CardTable.

Как показано на рисунке выше, объект y в области B ссылается на объект x в области A, и эта ссылочная связь охватывает две области. CardPage, на которой расположен объект y, равен 179. В наборе RSet области A адрес области B используется в качестве ключа, а нижний индекс 79 CardPage, на которой расположен объект b, является значением для записи отношения ссылки , тем самым завершая запись этой перекрестной ссылки. Однако гранулярность этого CardTable немного грубая, ведь CardPage имеет 512 байт, а в CardPage может быть несколько объектов. Следовательно, при сканировании метки необходимо сканировать всю страницу CardPage, связанную с набором RSet.Пример на приведенном выше рисунке — сканирование всех страниц CardPage с индексом 79 таблицы CardTable.

На самом деле конкретная реализация RSet of G1 в HotSpot VM сложнее, чем вышеописанное (описанное выше — лишь один из случаев, случай разреженной гранулярности). В приложении могут быть частые ссылки на обновления, что сделает RSets в некоторых регионах популярными регионами. G1 использует различную степень детализации для обработки популярности RSet.RSet можно разделить на три степени детализации: разреженная, точная и грубая. Когда степень детализации отличается, RSet использует другие структуры данных для записи ссылок из других точек входа в регион.Вышеупомянутый случай разреженной детализации. НижеEvaluating and improving remembered sets in the HotSpot G1 garbage collectorУпрощенное определение структуры данных RSet в G1 дано в статье.

1. Разреженная зернистость (saprse в структуре данных g1_rset выше)

В случае разреженной детализации это реализуется HashMap, ключ HashMap относится к адресу другого Regionr в этом Region, значением является массив, а элементом массива является индекс CardPage, соответствующий ссылочный объект в таблице CardTable.

2. Fine Grained (fine_grained в структуре данных g1_rset выше)

В случае мелкозернистости это также реализуется с помощью HashMap. Ключ HashMap относится к адресу другого региона в этом регионе, а значение представляет собой растровое изображение. Максимальное количество битов в растровом изображении представляет собой максимальное количество из CardPages, на которые может быть разделен регион. Верхнее значение 1 означает, что объект в CardPage в регионе ссылается на объект региона, к которому принадлежит RSet.

3. Крупнозернистый (грубый в структуре данных g1_rset выше)

В крупнозернистых случаях для реализации используется растровое изображение.Максимальное количество битов в растровом изображении представляет, на сколько регионов может быть разделена вся куча. Значение 1 на растровом изображении означает, что в других регионах есть объекты, которые ссылаются на объекты региона, к которому принадлежит набор RSet. Поскольку размер региона одинаков, начальный адрес каждого региона в растровом изображении можно вычислить через начальный адрес кучи.

G1 обычно использует потоки уточнения для асинхронного обслуживания RSet.Каждый поток будет использовать барьер после записи, введенный ранее, для записи ссылок между поколениями и ссылок от старого поколения к старому поколению в соответствующих локальных буферах журнала.Когда локальный буфер журнала заполнен, он будет обновляться до глобального буфера журнала, потоки уточнения специально обрабатывают глобальный буфер журнала для поддержания RSet.Когда потоки уточнения не могут эффективно обрабатывать глобальный буфер журнала, поток приложения будет обрабатывать буфер журнала вместе, но это отрицательно сказывается на производительности. потока приложений. В процессе сборки мусора, если глобальный буфер журнала не был обработан, поток GC будет обрабатывать эти буферы журнала.

void oop_field_store(oop* field, oop new_value) {
  pre_write_barrier(field);             // pre-write barrier: for maintaining SATB invariant
  *field = new_value;                   // the actual store
  post_write_barrier(field, new_value); // post-write barrier: for tracking cross-region reference
}
3.4 Коллекция (CSet)

Набор сбора (CSet), представляющий серию целевых разделов, которые освобождаются при каждой паузе GC. Во время любой паузы сбора все разделы CSet будут освобождены, а уцелевшие объекты будут перемещены в выделенные свободные разделы. Поэтому, будь то коллекция молодого поколения или смешанная коллекция, механизм работы одинаков. Коллекция CSet молодого поколения содержит только разделы молодого поколения, а смешанная коллекция будет использовать эвристический алгоритм для фильтрации разделов с наибольшим возвратом восстановления из разделов восстановления-кандидатов старого поколения и добавления их в CSet.

4 Углубленный анализ сборки мусора G1

​ Мы кратко представили схему памяти Heap в G1, цикл G1 с глобальной точки зрения, конкретную реализацию RSet и CSet. Далее мы представим фазу Young GC, фазу параллельной маркировки и Mix GC в G1. подробнее этап.

4.1 Стадия молодого GC

Подобно сборщику мусора поколений, когда в G1 нет региона Eden, способного вместить вновь созданный объект, срабатывает Young GC в G1, при этом каждый поток имеет соответствующий TLAB, а небольшие объекты сначала создаются напрямую в ТЛАБе. Ранее стало известно, что на стадии Young GC G1 будут переработаны только все Young Regions, Eden Regions и Survivor Regions, при этом, если коэффициент памяти старого поколения превысит заданный порог, Young GC будет завершить первоначальную работу по маркировке на параллельном этапе маркировки вместе. После каждого Young GC G1 повторно регулирует размер нового поколения в соответствии с текущим размером нового поколения, минимальным значением нового поколения, максимальным значением нового поколения и целевым временем паузы. Обычно ниже приводится журнал GC Young GC, чтобы увидеть, какие конкретно этапы Young GC включают. JDK использует версию JDK HotSpot 1.8.0_241, а параметры JVM следующие:

-XX:+UseG1GC -XX:G1HeapRegionSize=2m -Xms2g -Xmx2g -Xloggc:/Users/mac/Desktop/g1log -XX:+PrintGCDetails

-XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps

2021-12-29T10:03:58.217-0800: 0.244: [GC pause (G1 Evacuation Pause) (young), 0.0914253 secs]
   [Parallel Time: 90.3 ms, GC Workers: 8]
      [GC Worker Start (ms): Min: 244.0, Avg: 244.1, Max: 244.1, Diff: 0.1]
      [Ext Root Scanning (ms): Min: 0.1, Avg: 0.3, Max: 0.7, Diff: 0.7, Sum: 2.2]
      [Update RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
         [Processed Buffers: Min: 0, Avg: 0.0, Max: 0, Diff: 0, Sum: 0]
      [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.2, Diff: 0.2, Sum: 0.2]
      [Object Copy (ms): Min: 89.1, Avg: 89.6, Max: 89.8, Diff: 0.7, Sum: 716.5]
      [Termination (ms): Min: 0.0, Avg: 0.1, Max: 0.2, Diff: 0.2, Sum: 0.8]
         [Termination Attempts: Min: 1, Avg: 1.0, Max: 1, Diff: 0, Sum: 8]
      [GC Worker Other (ms): Min: 0.1, Avg: 0.2, Max: 0.2, Diff: 0.1, Sum: 1.3]
      [GC Worker Total (ms): Min: 90.1, Avg: 90.1, Max: 90.2, Diff: 0.1, Sum: 721.0]
      [GC Worker End (ms): Min: 334.2, Avg: 334.2, Max: 334.2, Diff: 0.1]
   [Code Root Fixup: 0.0 ms]
   [Code Root Purge: 0.0 ms]
   [Clear CT: 0.1 ms]
   [Other: 1.1 ms]
      [Choose CSet: 0.0 ms]
      [Ref Proc: 0.7 ms]
      [Ref Enq: 0.0 ms]
      [Redirty Cards: 0.1 ms]
      [Humongous Register: 0.1 ms]
      [Humongous Reclaim: 0.0 ms]
      [Free CSet: 0.0 ms]
   [Eden: 102.0M(102.0M)->0.0B(88.0M) Survivors: 0.0B->14.0M Heap: 102.0M(2048.0M)->98.0M(2048.0M)]
 [Times: user=0.12 sys=0.28, real=0.09 secs] 

Как показано в первой строке журнала GC вышеGC pause (G1 Evacuation Pause) (young)Представляет молодой GC, пауза GC которого равна G1. Работа Young GC делится на параллельную работу и другую работу, которые соответственно есть в журнале GC.[Parallel Time: 90.3 ms, GC Workers: 8]и[Other: 1.1 ms]. Параллельная работа является основной работой Young GC, и параллельная работа делится на следующие части.

1. Внешнее сканирование корневого каталога ([Ext Root Scanning (ms): ... раздел в журнале GC)

Отвечает за сканирование внешних корней CSet, таких как регистры, стеки потоков и т. д.

2. Обновление запомненных наборов (RSets) ([Обновить RS (мс): ... раздел в журнале GC)

Отвечает за обновление RSet.RSet в основном используется для записи ссылок из других точек региона, как подробно описано ранее.

3. Обработанные буферы (раздел [Обработанные буферы: ... в журнале GC)

Как упоминалось ранее, RSet поддерживается путем записи сначала буферов журнала, а затем их обновления.Обработанные буферы предназначены для обработки тех буферов журнала, которые не были обработаны потоком уточнения после запуска Young GC, что обеспечивает целостность RSet.

4. Сканировать RSets ([Сканировать RS (мс): ... раздел в журнале GC)

Отвечает за сканирование ссылок на другие регионы в наборах RSets, указывающих на этот регион. Это время сканирования будет сильно различаться, потому что популярность RSet различна, и для хранения используется структура данных с разной степенью детализации; время сканирования RSet будет самым трудоемким, когда ранее будет введено крупнозернистое.

5. Сканирование корня кода (раздел [Сканирование корня кода (мс): ... в журнале GC)

Отвечает за сканирование корневых ссылок скомпилированного исходного кода в CSet.

6. Копия объекта (раздел [Копия объекта (мс): ... в журнале GC)

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

7. Завершение ([Завершение (мс): ... и [Попытки завершения (мс): ...] в журнале GC)

Когда каждый поток GC Work завершит свою работу, он перейдет к конечной стадии.В это время завершивший работу поток Work будет синхронизироваться с другими потоками Work, и в то же время попытается использовать алгоритм кражи работы для получить работу других потоков, которые еще не завершили работу. Часть «Попытки завершения» показывает, что рабочий поток успешно получает работу и снова пытается завершиться после обработки. Этот процесс также попытается снова получить задачи других незавершенных рабочих потоков.

Другая работа, эта часть в основном представляет собой некоторые из их задач, включая выбор Regino в CSet, обработку ссылок, создание очереди ссылок, пометку страниц карточек как грязных страниц, выпуск CSet, обработку огромных объектов и т. д. Для получения более подробной информации о журнале G1 GC см.Collecting and reading G1 garbage collector logs - part 2.

Когда коэффициент памяти старого поколения превышает порог, указанный параметром -XX:InitiatingHeapOccupancyPercent, молодой GC, между прочим, завершит маркировку инициализации параллельной маркировки. В это время в журнале GC появитсяGC pause (G1 Evacuation Pause) (young) (initial-mark)Ключевая информация о , где начальная оценка представляет собой начальную оценку работы, проделанной незначительно во время Young GC.

4.2 Реализация SATB в G1

В начале статьи было указано, что сборщик мусора обычно использует алгоритм трехцветной маркировки для обработки процесса анализа ссылок на объекты на этапе маркировки.Решая проблему отсутствующих меток, G1 принимает Yuasa в вReal-Time Garbage Collection on General Purpose MachinesПредлагаемый алгоритм «моментального снимка в начале» (SATB).

Алгоритм SATB гарантирует, что все мусорные объекты идентифицируются снимками после начала параллельной маркировки. Вновь выделенные объекты в параллельном процессе маркировки считаются уцелевшими объектами, и их не нужно отслеживать и анализировать, что помогает сократить накладные расходы на маркировку. G1 поддерживает две глобальные битовые карты для одновременной маркировки, помеченные как предыдущая и следующая. Предыдущее растровое изображение сохраняет информацию метки предыдущей параллельной метки, а следующее растровое изображение сохраняет информацию метки параллельной метки, выполняемой в настоящее время или только что завершенной. Информация метки последней параллельной метки в предыдущем растровом изображении может использоваться непосредственно в этой метке. При этом каждый Регион имеет несколько важных указателей PTAMS (начальная позиция последней параллельной метки), NTAMS (начальная позиция следующей параллельной метки), Bottom (начальный адрес Region) и Top (используемый адрес Региона). ), End (конечный адрес Региона); Реализация TAMS — это аббревиатура top at mark start, то есть каждая параллельная метка будет помещать соответствующий указатель в ту же позицию, что и указатель Top, представляя конечное положение знака. В начале каждой параллельной метки указатель NTAMS повторно указывает на положение указателя Top.Когда параллельная метка заканчивается, указатель NTAMS и указатель PTAMS пересекаются, следующее растровое изображение и предыдущее растровое изображение меняются ролями, и новое следующее растровое изображение очищается, то есть исходное предыдущее растровое изображение очищается.

На приведенном выше рисунке показаны позиции указателя внизу, PTAMS, NTAMS, вверху и конце региона в параллельном процессе маркировки, а также значение области между указателями. Белый, серый и черный в интервале можно приблизительно понять как три цвета в методе трехцветной маркировки.

[Внизу, PTAMS) интервал

Этот интервал представляет собой интервал последней параллельной метки, а PTAMS является конечной позицией последней одновременной метки.Информация о последней одновременной метке в этом интервале может быть непосредственно использована текущей параллельной меткой, то есть текущей параллельной меткой. знает последнее растровое изображение через последнее растровое изображение.Интервалы, которые являются мусором и которые являются живыми объектами.

[PTAMS, NTAMS) интервал

Этот интервал представляет собой текущий интервал параллельной маркировки. NTAMS — это конечная позиция этой параллельной маркировки. Когда параллельная маркировка начинается, G1 создаст снимок для интервала [PTAMS, NTAMS), который фактически является следующим битовым массивом, а затем обработает растровое отображение адресов, помечая объекты по этим адресам как мусорные или живые. Фактический процесс маркировки заключается в перемещении указателя из положения указателя PTAMS в положение указателя NTAMS.

[NTAMS, Верхний) интервал

Этот интервал представляет объекты, вновь сгенерированные потоком приложения во время процесса параллельной маркировки.Как упоминалось ранее, вновь выделенные объекты во время процесса параллельной маркировки считаются уцелевшими объектами, поэтому интервал на приведенном выше рисунке полностью черный. В начале параллельной метки указатель Top и указатель NTAMS находятся в одном и том же положении.Когда поток приложения генерирует новый объект, указатель Top перемещается вправо в направлении указателя End.

[Верх, Конец) интервал

Этот интервал представляет собой неиспользуемое пространство в регионе.

Очевидно, поток GC будет обрабатывать только диапазон **[PTAMS, NTAMS)Работа по маркировке выполняется во время выполнения потока приложения.[Нижний, Верхний) интервалвлиятельный. пара потоков приложений[Нижний, Верхний) интервалсередина[NTAMS, Верхний) интервалВоздействие потока GC не влияет на параллельную работу по маркировке потока GC, поскольку вновь добавленные объекты этой части потока приложения считаются уцелевшими объектами. пара потоков приложений[Нижний, Верхний) интервалсередина[PTAMS, NTAMS) интервалВоздействие потока GC может повлиять на параллельную работу маркировки потока GC.G1 обеспечивает правильность маркировки через введенный ранее барьер предварительной записи, то есть если поток приложения находится в[PTAMS, NTAMS) интервалДобавлена ​​ссылка черного объекта на белый объект, и белый объект будет установлен на серый объект во время внутренней обработки барьера предварительной записи, чтобы объект можно было снова пометить, не вызывая пропущенных меток. пара потоков приложений[Нижний, Верхний) интервалсерединаВлияние интервала [Bottom, PTAMS)** может повлиять на параллельную работу маркировки потока GC. Как G1 обрабатывает это, необходимо проверить, и предполагается, что здесь следует использовать технологию барьера записи.

После приведенного выше введения давайте взглянем на статью Sun G1.Garbage-First Garbage CollectionЭта диаграмма в разделе «Первоначальная пауза/параллельная оценка» должна прояснить ситуацию.

На этапе Initial Marking, когда регион отмечается в первый раз, PrevBitmap пуст, а NextBitmap содержит фотографию блока интервала **[PrevTAMS, NextTAMS)**. После завершения одновременной маркировки он будет определить, какие объекты мусора в растровом изображении, указатель PrevTAMS и указатель Bottom. Положение такое же, и указатель NextTAMS находится в том же положении, что и указатель Top.

этап замечаний,[PrevTAMS, NextTAMS) интервалУцелевшие объекты и мусорные объекты помечаются, а NextBitmap изменяется: черная часть представляет отмеченный уцелевший объект, а белая часть — мусорный объект. В то же время, поскольку приложение создает новый объект, положение указателя Top перемещается вправо от указателя NextTAMS.

На этапе Cleanup/GC Pauses роли NextBitmap и PrevBitmap меняются, а указатель NextTAMS и указатель PrevTAMS меняются местами.

На начальной фазе маркировки нового раунда указатель NextTAMS снова указывает на указатель Top, а PrevBitmap гарантирует последнюю информацию о маркировке.В интервале **[PrevTAMS, NextTAMS)** в NextBitmap есть фотографии блоков.

Новый раунд маркировки фазы «Замечание», а затем повторите вышеописанное B.

Новый раунд маркировки: этап «Примечание», этап «Очистка/паузы GC» и повторение описанного выше C.

4.3 Фаза одновременной оценки

Этап параллельной маркировки в основном помечает объекты мусора, которые будут собраны во время Mix GC, а затем сортирует их в соответствии с объемом памяти, который может освободить регион, и добавляет эти регионы в список доступных регионов. Этап одновременной маркировки можно разделить на пять этапов, включая начальную маркировку, сканирование корневой области, параллельную маркировку, примечание и очистку.

Начальная стадия отметки

Когда соотношение памяти старого поколения превышает пороговое значение, указанное параметром -XX:InitiatingHeapOccupancyPercent, будет запущена параллельная маркировка. Первым этапом параллельной маркировки является Initial Mark. Это этап STW, который сканирует только объекты, на которые непосредственно ссылается GCRoot. сканировать объекты, на которые непосредственно ссылается GCRoot, Young GC, между прочим, завершит работу Initial Mark. Журналы GC обычно содержатGC pause (G1 Evacuation Pause) (young) (initial-mark)Ключевая информация, где начальная оценка представляет собой начальную работу по оценке, выполненную способом, когда выполняется Young GC.

Этап сканирования корневого региона

На самом деле сканируется объект, на который ссылается Survivor Region нового поколения.Этот этап должен быть завершен до следующей паузы GC, потому что, если куча хочет сканировать уцелевший объект, сначала должен быть идентифицирован объект, на который ссылается Survivor Region.

Параллельная стадия маркировки

На этапе параллельной маркировки потоки GC и потоки приложения являются параллельными, а количество параллельных потоков GC можно указать с помощью -XX:ConcGCThreads. Как упоминалось выше, G1 использует барьер предварительной записи для решения проблемы отсутствия маркировки, вызванной тем, что поток приложения обновляет моментальный снимок графа объектов, созданный на этапе параллельного запуска в параллельном процессе маркировки, в каждом потоке. Параллельная фаза маркировки, между прочим, завершит подсчет каждого объекта Region, чтобы потом было удобно подсчитывать, какие регионы могут освободить больше памяти.

Этап замечаний

Эта стадия фактически является последней стадией маркировки, которая будет SWT.Эта стадия отвечает за обработку оставшихся ссылок.На этой стадии будут обрабатываться необработанные ссылки,записанные предыдущим барьером записи SATB. Однако она существенно отличается от реплики CMS, то есть пауза реплики G1 нужна только для сканирования буфера SATB, тогда как реплика CMS требует повторного сканирования всех грязных карт и всего корневого набора, и в это время все новое поколение будет рассматриваться как часть корневого набора, реплика CMS может быть очень медленной.

Этап очистки

На этом этапе будет STW, и его основная задача — сбросить состояние метки, например, роли NextBitmap и PrevBitmap меняются местами, как описано выше, а указатель NextTAMS и указатель PrevTAMS меняются местами. При этом, если обнаружится, что есть Регион без уцелевших объектов, Регион будет сразу очищен и добавлен в список свободных Регионов. Разумеется, на этом этапе также завершается статистика того, сколько мусора можно собрать в каждом Регионе, чтобы можно было быстро определить CSet при передаче объекта Mix GC.

4.4 Стадия смешанной ГХ

Этап MixGC в основном отвечает за переработку некоторых регионов старого поколения и всех новых поколений.G1 будет перерабатывать регионы, отмеченные на этапе параллельной маркировки, в соответствии с установленным целевым временем паузы -XX:MaxGCPauseMillis, в соответствии с размером области пространство памяти, которое может быть освобождено. То есть этап MixGC будет содержать несколько MixGC. Когда G1 обнаружит, что пространство памяти, полученное путем освобождения объектов мусора, слишком мало, он остановит MixGC. Во время MixGC ключевая информация о **паузе GC (G1 Evacuation Pause) (mixed)** появится в журнале GC. В качестве итоговой стратегии, когда памяти, освобождаемой процессом сборки мусора G1, недостаточно для удовлетворения требований к памяти для новых объектов в приложении, G1 будет использовать полный сборщик мусора для обработки всех регионов.

Суммировать

В этой статье подробно анализируется лежащий в основе принцип реализации сборщика мусора G1.Хотя конкретный исходный код сборщика мусора G1 не задействован, в основном анализируются знания, связанные с G1, от поверхностного до глубокого. Я надеюсь, что прочитав эту статью, вы что-то почерпнете.В связи с моими ограниченными возможностями, я надеюсь, что статья неверна. Наконец, добро пожаловать, чтобы обратить внимание на личный публичный аккаунт, чтобы понять исходный код.

Ссылаться на

Java Performance Companion

Руководство по алгоритмам сборки мусора Искусство автоматического управления памятью

Управление памятью в виртуальной машине Java HotSpot™

Plumbr Handbook Java Garbage Collection

Java Garbage Collection Basics

G1: One Garbage Collector To Rule Them All

HotSpot Virtual Machine Garbage Collection Tuning Guide

Collecting and reading G1 garbage collector logs - part 2

[HotSpot VM] Спросите принцип алгоритма G1

Виртуальная машина Java 07 — сборщик мусора G1

Garbage-First Garbage Collection

Minor GC vs Major GC vs Full GC

Real-Time Garbage Collection on General Purpose Machines

memorymanagement.org Tri-color Marking

Wiki Tri-color Marking

On-the-Fly Garbage Collection: An Exercise in Cooperation

Uniprocessor Garbage Collection Techniques

Evaluating and improving remembered sets in the HotSpot G1 garbage collector

Интервьюер спросил меня, как узнать, когда вы мусор?

конец

Оригинальность - это непросто. Лайк, просмотр и пересылка - большая поддержка для меня. Уделение внимания официальному аккаунту и понимание исходного кода - самая большая поддержка для меня. В то же время я верю, что буду делиться большим количеством галантерейных товаров, я буду расти вместе с вами и буду прогрессировать вместе с вами.