1. Обзор
В этом кратком руководстве мы продемонстрируем основы различных реализаций сборки мусора (GC) JVM
. Затем мы узнаем, как включить определенный тип сборки мусора в наших приложениях.
2. Краткое введение в сборку мусора
Учитывая название, кажется, что сборка мусора
занимается поиском и удалением мусора из памяти. Однако на самом деле сборка мусора
отслеживает каждый объект, доступный в пространстве кучи JVM, и удаляет неиспользуемые.
По сути, GC
работает в два простых шага, известных как Mark and Sweep:
- Пометка — здесь сборщик мусора определяет, какие части памяти используются, а какие нет.
- Очистка — на этом шаге удаляются объекты, выявленные на этапе «отметки».
Преимущества:
- Нет ручной обработки выделения/освобождения памяти, поскольку неиспользуемое пространство памяти автоматически обрабатывается
сборщиком мусора
- Отсутствие накладных расходов на обработку
висячего указателя
- Автоматическое управление утечками
памяти
(GC
сам по себе не может гарантировать полное решение проблемы утечки памяти, однако он позаботится о значительной ее части)
Недостатки:
- Поскольку
JVM
должна отслеживать создание/удаление ссылок на объекты, для этого действия требуется больше ресурсов ЦП, чем для исходного приложения. Это может повлиять на производительность запросов, требующих большого объема памяти. - Программисты не имеют возможности контролировать распределение процессорного времени, выделяемого на освобождение объектов, которые больше не нужны.
- Использование некоторых реализаций GC может привести к непредсказуемой остановке приложения.
- Автоматизированное управление памятью будет не таким эффективным, как правильное выделение/освобождение памяти вручную.
3. Реализации сборщика мусора
JVM имеет пять типов реализации GC
:
- Серийный сборщик мусора
- Параллельный сборщик мусора
- Сборщик мусора CMS
- Сборщик мусора G1
- Z сборщик мусора
3.1. Серийный сборщик мусора
Это самая простая реализация сборщика мусора, так как она в основном работает с одним потоком. В результате эта реализация GC
замораживает все потоки приложения при запуске . Поэтому не рекомендуется использовать его в многопоточных приложениях, таких как серверные среды.
Тем не менее, на QCon 2012 инженеры Twitter
сделали отличный доклад о производительности Serial Garbage Collector,
что является хорошим способом лучше понять этот сборщик.
Serial GC — это предпочтительный сборщик мусора для большинства приложений, которые не требуют небольшого времени паузы и работают на клиентских компьютерах. Чтобы включить Serial Garbage Collector
, мы можем использовать следующий аргумент:
java -XX:+UseSerialGC -jar Application.java
3.2. Параллельный сборщик мусора
Это сборщик мусора по умолчанию для JVM
,
который иногда называют сборщиками пропускной способности. В отличие от Serial Garbage Collector
, он использует несколько потоков для управления пространством кучи, но также замораживает другие потоки приложения во время выполнения GC
.
Если мы используем этот GC
, мы можем указать максимальное количество потоков сборки мусора и время паузы, пропускную способность и занимаемую площадь
(размер кучи).
Количество потоков сборщика мусора можно контролировать с помощью параметра командной строки -XX:ParallelGCThreads=<N>
.
Целевое максимальное время паузы (промежуток [в миллисекундах] между двумя GC
) указывается с помощью параметра командной строки -XX:MaxGCPauseMillis=<N>
.
Время, затраченное на сборку мусора, по сравнению со временем, затраченным вне сборки мусора, называется максимальной целевой пропускной способностью и может быть указано с помощью параметра командной строки -XX:GCTimeRatio=<N>.
Максимальный размер кучи (объем памяти кучи, который требуется программе во время работы) указывается с помощью параметра -Xmx<N>.
Чтобы включить Parallel Garbage Collector
, мы можем использовать следующий аргумент:
java -XX:+UseParallelGC -jar Application.java
3.3. Сборщик мусора CMS
Реализация Concurrent Mark Sweep (CMS)
использует несколько потоков сборщика мусора для сборки мусора. Он разработан для приложений, которые предпочитают более короткие паузы для сборки мусора и могут позволить себе совместно использовать ресурсы процессора со сборщиком мусора во время работы приложения.
Проще говоря, приложения, использующие этот тип сборщика мусора, в среднем отвечают медленнее, но не перестают отвечать для выполнения сборки мусора.
Здесь следует отметить, что, поскольку этот GC
является параллельным, вызов явной сборки мусора, такой как использование System.gc()
во время работы параллельного процесса, приведет к сбою/прерыванию параллельного режима
.
Если более 98% всего времени тратится на сборку мусора
CMS
, а восстанавливается менее 2% кучи, то сборщиком CMS
выдается ошибка OutOfMemoryError
. При необходимости мы можем отключить эту функцию, добавив в командную строку параметр -XX:-UseGCOverheadLimit
.
``
Этот сборщик также имеет режим, известный как инкрементный режим, который устарел в Java SE 8 и может быть удален в будущем основном выпуске.
Чтобы включить сборщик мусора CMS
, мы можем использовать следующий флаг:
java -XX:+UseParNewGC -jar Application.java
Начиная с Java 9 сборщик мусора CMS объявлен устаревшим . Поэтому JVM печатает предупреждающее сообщение, если мы пытаемся его использовать:
>> java -XX:+UseConcMarkSweepGC --version
Java HotSpot(TM) 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated
in version 9.0 and will likely be removed in a future release.
java version "9.0.1"
Более того, Java 14 полностью отказалась от поддержки CMS:
>> java -XX:+UseConcMarkSweepGC --version
OpenJDK 64-Bit Server VM warning: Ignoring option UseConcMarkSweepGC;
support was removed in 14.0
openjdk 14 2020-03-17
3.4. Сборщик мусора G1
Сборщик мусора G1 (Garbage First)
предназначен для приложений, работающих на многопроцессорных машинах с большим объемом памяти. Он доступен в JDK7 Update 4
и в более поздних версиях.
Сборщик G1
заменит сборщик CMS
, так как он более эффективен.
В отличие от других сборщиков, сборщик G1
разбивает кучу на набор областей кучи одинакового размера, каждая из которых представляет собой непрерывный диапазон виртуальной памяти. При сборке мусора G1
показывает параллельную глобальную фазу маркировки (т. е. фазу 1, известную как маркировка)
, чтобы определить живучесть объектов во всей куче.
После завершения фазы маркировки G1
знает, какие регионы в основном пусты. Сначала он собирается в этих областях, что обычно дает значительное количество свободного пространства (т. е. фаза 2, известная как подметание).
Вот почему этот метод сборки мусора называется Garbage-First.
Чтобы включить сборщик мусора G1
, мы можем использовать следующий аргумент:
java -XX:+UseG1GC -jar Application.java
3.5. Изменения Java 8
Java 8u20
представила еще один параметр JVM
для сокращения ненужного использования памяти за счет создания слишком большого количества экземпляров одной и той же строки.
Это оптимизирует память кучи, удаляя повторяющиеся значения String
в глобальный одиночный массив char[] .
Мы можем включить этот параметр, добавив -XX:+UseStringDeduplication
в качестве параметра JVM
.
3.6. Z сборщик мусора
ZGC (Z Garbage Collector)
— это масштабируемый сборщик мусора с малой задержкой, дебютировавший в Java 11 в качестве экспериментального варианта для Linux. JDK
14 представил ZGC
для операционных систем Windows и macOS. ZGC
получил производственный статус, начиная с Java 15.
ZGC
выполняет всю дорогостоящую работу одновременно, не останавливая выполнение потоков приложений более чем на 10 мс , что делает его подходящим для приложений, требующих низкой задержки. Он использует барьеры нагрузки с цветными указателями для выполнения параллельных операций во время работы потоков, и они используются для отслеживания использования кучи.
Эталонная раскраска (цветные указатели) является основной концепцией ZGC
. Это означает, что ZGC
использует некоторые биты (биты метаданных) ссылки для обозначения состояния объекта. Он также обрабатывает кучи размером от 8 МБ до 16 ТБ . Кроме того, время паузы не увеличивается с размером кучи, живого набора или корневого набора.
Подобно G1, сборщик мусора Z
разделяет кучу, за исключением того, что области кучи могут иметь разные размеры.
Чтобы включить сборщик мусора Z
, мы можем использовать следующий аргумент в версиях JDK
ниже 15:
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC Application.java
Начиная с версии 15, нам не нужен экспериментальный режим:
java -XX:+UseZGC Application.java
Следует отметить, что ZGC
не является сборщиком мусора по умолчанию.
4. Вывод
В этой статье мы рассмотрели различные реализации сборки мусора JVM
и варианты их использования.
Более подробную документацию можно найти здесь .