Введение

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

Java - это объектно-ориентированный язык программирования, который включает автоматическую сборку мусора. Java автоматически выделяет и освобождает память, поэтому программы не обременены этой задачей. Теперь (Java-12) в Java есть семь типов сборщиков мусора,

  1. Серийный сборщик мусора
  2. Параллельный сборщик мусора
  3. Сборщик мусора CMS
  4. Сборщик мусора G1
  5. Сборщик мусора Эпсилон
  6. Z сборщик мусора
  7. Сборщик мусора Шенандоа

Пятый и шестой сборщики мусора представили в java 11, а седьмой - в java 12. В большинстве приложений в производстве используются первые четыре типа сборщиков мусора. Так как последние три сборщика мусора появились недавно.

Нам нужно беспокоиться о сборщиках мусора?

Да, в самом деле. Мы должны беспокоиться о GC и его поведении. Потому что это может дать значительную разницу в производительности. У каждого GC есть свои преимущества и недостатки. Как разработчики, мы должны иметь четкое представление о поведении всех сборщиков мусора, и мы должны выбрать сборщик мусора на основе нашего бизнес-сценария. Мы можем выбрать сборщик мусора, передав выбор в качестве аргумента JVM.

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

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

Чтобы включить последовательный сборщик мусора, мы можем использовать следующий аргумент:

java -XX: + UseSerialGC -jar Application.java

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

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

Чтобы включить параллельный сборщик мусора, мы можем использовать следующий аргумент:

java -XX: + UseParallelGC -jar Application.java

Если мы используем этот GC, мы можем указать максимальное количество потоков сборки мусора и время паузы, пропускную способность и размер (размер кучи)

Количество потоков сборщика мусора можно контролировать с помощью параметра командной строки.

-XX: ParallelGCThreads = ‹N›

Максимальное целевое время паузы (промежуток [в миллисекундах] между двумя GC) указывается с помощью параметра командной строки.

-XX: MaxGCPauseMillis = ‹N›

Целевая максимальная пропускная способность (измеряется относительно времени, затраченного на сборку мусора по сравнению с временем, затраченным на сборку мусора), указывается параметром командной строки.

-XX: GCTimeRatio = ‹N›

Максимальный размер кучи (объем памяти кучи, который требуется программе во время работы) указывается с помощью параметра -Xmx ‹N›.

3. Сборщик мусора CMS

Сборщик мусора Concurrent Mark Sweep (CMS) использует несколько потоков сборщика мусора для сборки мусора. Он сканирует память кучи, чтобы пометить экземпляры для удаления, а затем очистить отмеченные экземпляры. Он разработан для приложений, которые предпочитают более короткие паузы при сборке мусора и могут позволить себе совместно использовать ресурсы процессора со сборщиком мусора во время работы приложения.

Сборщик мусора CMS удерживает все потоки приложений только в следующих двух сценариях.

  1. При маркировке ссылочных объектов в пространстве старого поколения.
  2. Любое изменение памяти кучи параллельно с сборкой мусора.

По сравнению с параллельным сборщиком мусора, сборщик CMS использует больше ЦП, чтобы обеспечить лучшую пропускную способность приложения. Если мы можем выделить больше ЦП для повышения производительности, то сборщик мусора CMS будет предпочтительнее параллельного сборщика.

Чтобы включить сборщик мусора CMS, мы можем использовать следующий аргумент:

java -XX: + USeParNewGC -jar Application.java

4. Сборщик мусора G1

Сборщик мусора G1 (сначала мусор) разработан для приложений, работающих на многопроцессорных машинах с большим объемом памяти. Он доступен начиная с JDK7 Update 4 и в более поздних выпусках.

Он разделяет память кучи на регионы и параллельно выполняет сбор данных в них. G1 также сжимает свободное пространство кучи на ходу сразу после освобождения памяти. Но сборщик мусора CMS сжимает память в ситуациях остановки мира (STW). Сборщик G1 заменит сборщик CMS, поскольку он более эффективен.

В коллекторе G1 есть две фазы;

  1. Маркировка
  2. Подметание

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

После завершения этапа отметки G1 знает, какие области в основном пусты. Сначала он собирается в этих областях, что обычно дает значительный объем свободного пространства . Вот почему этот метод сборки мусора называется Garbage-First.

Чтобы включить сборщик мусора G1, мы можем использовать следующий аргумент:

java -XX: + UseG1GC -jar Application.java

5. Сборщик мусора Epsilon

Epsilon - это нерабочий или пассивный сборщик мусора. Он выделяет память для приложения, но не собирает неиспользуемые объекты. Когда приложение исчерпывает кучу Java, JVM завершает работу. Это означает, что сборщик мусора Epsilon позволяет приложениям исчерпывать память и давать сбой.

Целью этого сборщика мусора является измерение и управление производительностью приложений. Активные сборщики мусора - это сложные программы, которые запускаются внутри JVM вместе с вашим приложением. Epsilon устраняет влияние GC на производительность. Нет никаких циклов сборки мусора или препятствий для чтения или записи. При использовании Epsilon GC код выполняется изолированно. Epsilon помогает визуализировать, как сборка мусора влияет на производительность приложения и каков порог памяти, поскольку он показывает, когда он заканчивается. В качестве примера. Если мы думаем, что для нашего приложения нужен только один гигабайт памяти, мы можем запустить его с -Xmx1g и посмотреть, как оно себя ведет. Если этого распределения памяти недостаточно, перезапустите его с дампом кучи. Обратите внимание, что мы должны включить эту опцию, чтобы получить дамп кучи. Мы можем использовать этот аргумент, чтобы получить дамп кучи, когда приложение вылетает из-за нехватки памяти.

XX: HeapDumpOnOutOfMemoryError

Если нам нужно выжать максимум из производительности нашего приложения, Epsilon может стать вашим лучшим вариантом для ГХ. Но нам нужно иметь полное представление о том, как наш код использует память. Если он почти не создает мусора или вы точно знаете, сколько памяти он использует за период своей работы, Epsilon - жизнеспособный вариант.

Чтобы включить сборщик мусора Epsilon, мы можем использовать следующий аргумент:

java -XX: + UseEpsilonGC -jar Application.java

6. Сборщик мусора Z

ZGC выполняет всю дорогостоящую работу одновременно, не останавливая выполнение потоков приложений более чем на 10 мс, что делает его подходящим для приложений, которым требуется низкая задержка и / или используется очень большая куча. Согласно документации Oracle, он может обрабатывать многотерабайтные кучи. Oracle представила ZGC в Java 11. Сборщик мусора Z выполняет свои циклы в своих потоках. Приложение приостанавливает работу в среднем на 1 мс. Коллекторы G1 и Parallel в среднем составляют около 200 мс.

В Java 12 Oracle добавила исправления производительности и выгрузку классов, хотя Z все еще находится в экспериментальном состоянии. Он доступен только в 64-разрядной версии Linux. Но ZGC использует преимущества 64-битных указателей с техникой, называемой раскраской указателя. Цветные указатели хранят дополнительную информацию об объектах в куче. Это одна из причин, по которой он ограничен 64-битной JVM. В этой статье подробно описан этот сценарий (https://www.opsian.com/blog/javas-new-zgc-is-very-exciting/).

ZGC выполняет маркировку в три этапа.

1. Короткая фаза остановки мира - проверяет корни сборщика мусора, локальные переменные, указывающие на остальную часть кучи. Общее количество этих корней обычно минимально и не зависит от размера нагрузки, поэтому паузы ZGC очень короткие и не увеличиваются по мере роста кучи.

2. Параллельная фаза - он просматривает граф объектов и проверяет цветные указатели, отмечая доступные объекты. Барьер нагрузки предотвращает конфликты между фазой сборки мусора и действиями любого приложения.

3. Этап перемещения. Он перемещает живые объекты, чтобы освободить большие участки кучи, чтобы ускорить выделение. Когда начинается фаза перемещения, ZGC делит кучу на страницы и работает с одной страницей за раз. Когда ZGC завершает перемещение любых корней, остальная часть перемещения выполняется в параллельной фазе.

ZGC сам попытается установить количество потоков, и обычно это правильно. Но если ZGC имеет слишком много потоков, ваше приложение будет голодать. Если его недостаточно, вы создадите мусор быстрее, чем сборщик мусора сможет его собрать. Этапы ZGC иллюстрируют, как он управляет большими кучами, не влияя на производительность по мере роста памяти приложения.

Чтобы включить Z Garbage Collector, мы можем использовать следующий аргумент:

java -XX: + UseZGC -jar Application.java

7. Шенандоа

Shenandoah - это сборщик мусора со сверхмалым временем паузы, который сокращает время паузы сборщика мусора, выполняя больше работы по сборке мусора одновременно с запущенной программой Java. CMS и G1 одновременно выполняют маркировку живых объектов. Шенандоа добавляет одновременное уплотнение.

Shenandoah использует области памяти, чтобы управлять тем, какие объекты больше не используются, а какие находятся в рабочем состоянии и готовы к сжатию. Shenandoah также добавляет указатель пересылки к каждому объекту кучи и использует его для управления доступом к объекту. В дизайне Шенандоа параллельные циклы ЦП и пространство обмениваются на улучшения времени паузы. Указатель пересылки позволяет легко перемещать объекты, но агрессивные движения означают, что Shenandoah использует больше памяти и требует больше параллельной работы, чем другие сборщики мусора. Но он выполняет дополнительную работу с очень короткими паузами для остановки.

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

  1. Первая остановка в цикле. Он подготавливает кучу для одновременной маркировки и сканирует корневой набор. Как и ZGC, длина этой паузы соответствует размеру корневого набора, а не кучи.
  2. Затем параллельная фаза просматривает кучу и определяет доступные и недоступные объекты.
  3. Третий завершает процесс маркировки путем слива отложенных обновлений кучи и повторного сканирования корневого набора. Эта фаза запускает вторую паузу цикла. Количество ожидающих обновлений и размер корневого набора определяют продолжительность паузы.
  4. Затем другая параллельная фаза копирует объекты из областей, идентифицированных на последней фазе метки. Этот процесс отличает Shenandoah от других сборщиков мусора, поскольку он агрессивно уплотняет кучу параллельно с потоками приложений.
  5. Следующая фаза запускает третью (и самую короткую) паузу в цикле. Это гарантирует, что все потоки сборщика мусора завершили эвакуацию.
  6. По завершении параллельная фаза просматривает кучу и обновляет ссылки на объекты, перемещенные ранее в цикле.
  7. Последняя остановка мира в цикле завершает обновление ссылок путем обновления корневого набора. При этом перерабатывает эвакуированные регионы.
  8. Наконец, последняя фаза восстанавливает эвакуированные регионы, в которых теперь нет ссылок.

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

1. Адаптивный: отслеживает циклы сборки мусора и запускает следующий цикл, чтобы он завершился до того, как приложение исчерпает кучу. Эта эвристика является режимом по умолчанию.

2. Статический: запускает цикл сборки мусора в зависимости от занятости кучи и давления выделения.

3. Компактный: непрерывное выполнение циклов ГХ. Shenandoah начинает новый цикл сразу после завершения предыдущего или в зависимости от количества выделенной кучи с момента последнего цикла. Эта эвристика требует дополнительных затрат на пропускную способность, но обеспечивает наилучшее использование пространства.

Shenandoah необходимо собирать кучу быстрее, чем ее выделяет обслуживаемое им приложение. Если давление выделения слишком велико и недостаточно места для нового выделения, произойдет сбой. В Shenandoah есть настраиваемые механизмы для этой ситуации.

  • Темп размещения: если Shenandoah начинает отставать в скорости выделения, он останавливает потоки выделения, чтобы наверстать упущенное. Прилавков обычно достаточно для небольших всплесков выделения. В Shenandoah задержки не превышают 10 мс. Если кардиостимуляция не удалась, Shenandoah перейдет к следующему шагу: дегенерированный сборщик мусора.
  • Вырожденный сборщик мусора: если происходит сбой выделения, Shenandoah начинает фазу остановки мира. Он использует фазу для завершения текущего цикла GC. Поскольку Stop-the-World не борется с заявкой на ресурсы, цикл должен завершиться быстро и устранить нехватку распределения. Часто вырожденный цикл происходит после того, как большая часть работы цикла уже завершена, поэтому остановка мира кратковременна. Однако журнал GC сообщит об этом как о полной паузе.
  • Полный сборщик мусора: если и синхронизация, и дегенерированный сборщик мусора не работают, Shenandoah возвращается к полному циклу сборки мусора. Этот последний сборщик мусора гарантирует, что приложение не выйдет из строя с ошибкой нехватки памяти, если не останется кучи.

Shenandoah предлагает те же преимущества, что и ZGC, с большими кучами, но с большим количеством возможностей настройки. В зависимости от характера вашего приложения вам могут подойти различные эвристики. Его время паузы может быть не таким коротким, как у ZGC, но оно более предсказуемо.

Чтобы включить сборщик мусора Shenandoah, мы можем использовать следующий аргумент:

java -XX: + UseShenanodoahC -jar Application.java

Вывод

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

Ссылка

  1. Https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
  2. Https://www.baeldung.com/jvm-garbage-collectors
  3. Https://dzone.com/articles/java-garbage-collection-3
  4. Https://www.opsian.com/blog/javas-new-zgc-is-very-exciting/
  5. Https://openjdk.java.net/projects/shenandoah/
  6. Https://docs.oracle.com/en/java/javase/12/gctuning/z-garbage-collector1.html#GUID-A5A42691-095E-47BA-B6DC-FB4E5FAA43D0
  7. Http://clojure-goes-fast.com/blog/shenandoah-in-production/