В некоторых языках есть механизм автоматического и безопасного освобождения оперативной памяти, ранее выделенной объектам в программе. Влияние разработчика на этот процесс опосредованное, прямого управления нет. Этот механизм принято называть Garbage collector (GC).

Структура памяти в Java

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

Некоторые языки возлагают ответственность за управление памятью на разработчика, например C, C++, Rust. В таком случае разработчик должен сам, в коде, вызвать метод удаления объекта, чтобы освобождать память. Если этого не делать, то можно получить утечку памяти.

Наличие GC в языке можно сравнить с коробкой автомат в автомобиле: вы получаете удобство, но в какой-то степени теряете контроль.

Вы получаете следующие преимущества:

  • Ускорение разработки.
  • Защита от утечек памяти.

B следующие недостатки:

  • Потребление дополнительных вычислительных ресурсов.
  • Утечки памяти :)
  • StopTheWorld

Производительность GC

Вам быстро, дешево или качественно?

  • Throughput. Объем вычислительных ресурсов CPU, затрачиваемых на работу GC.
  • Предсказуемость. На какое время прерывается работа приложения.
  • Footprint. Объем используемой памяти.

Работа GC

Глобально у GC есть всего 2 задачи:

  • Найти мусор. То есть понять, что объект больше не будет использоваться.
  • И собрать мусор. Уничтожить такие объекты, чтобы на их месте можно было алоцировать новые.

NOTE

В процессе своей работы GC не потребляет память в Heap

Алгоритмы поиска мусора

Reference Counting

Этот алгоритм подсчитывает количество ссылок на каждый объект. Когда счетчик ссылок достигает нуля, объект считается недоступным.

Есть довольно много ситуаций, когда данный способ не работает. Например, циклический граф, где объекты ссылаются друг на друга, но они все являются мусором.

Tracing

Подсчет ссылок. Это наиболее распространенный алгоритм маркировки. Он начинается с изначально достижимых, “корневых” (GC Root), объектов и отслеживает все объекты, доступные от этих корней.

Что может быть выбрано в качестве GC Root?

Локальные переменные и статические переменные в Main классе и main методе, поток, который выполняет main, статические переменные, ссылки из JNI.

Подходы к сбору мусора

Потоки GC

Search thread

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

GC thread

  • Отдельный поток, который занимается сборкой мусора.
  • Таких потоков может быть много.
  • Имеет несколько причин для старта.
  • Может быть причиной StopTheWorld

Причины старта GC

Главные:

  • Allocation Failure. JVM попыталась выделить область памяти под новый объект, но памяти не хватило
  • GC Locker. Кто-то подал сигнал на уборку.

Остальные:

  • Adaptive Size Ergonomics.
  • Allocation Profiler. Профайлер оказывает влияние на сборку мусора искажая показатели.
  • Heap Inspection.
  • Heap Dump.
  • No GC. Если сборка мусора еще не запускалась или проходила давольно давно.
  • Last Ditch Collection.
  • Perm Generation Ful.
  • Meradata GC Threshold.

Minor Collection

Если количество используемой Eden Space памяти превышает некоторый заданный объем, то GC может выполнить быструю (minor) сборку мусора. По сравнению с полной сборкой мусора, данный процесс занимает немного времени и затрагивает только область молодого поколения, - устаревшие объекты без ссылок удаляются, а выжившие перемещаются в Survivor Space.

Full Collection

В отличии от minor сборок охватывает весь Heap и занимает больше времени.

Сборщики

  • Epsilon GC. Не собирает мусор :)
  • Serial GC. Морально устарел, но подойдет для консольных приложений.
  • Parallel GC. Подходит для всех остальных случаев.
  • Parallel Compacting Collector.
  • Concurrent Mark Sweep. Минимизирует время простоя в приложениях с долгоживущими данными. Подходит для web-приложений.
  • Garbage First. Хорошо подходит для больших объемов памяти в сочетании с небольшими объектами.
  • Ultra-low latency

По умолчанию обычно используется или Serial или Parallel GC.

Как повлиять на сборку?

  • Писать код с учетом особенностей работы GC. Неблагодарный труд.
  • Использовать флаги JVM

Команда System.gc() носит рекомендательный характер. Разработчик рекомендует JVM запустить GC, но JVM может этого и не сделать.

Мониторинг работы GC

Минимальные накладные расходы

Параметры VM

  • -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
  • -Xlog:gc Показывает время StopTheWorld.
    • Стоит помнить про Safe Point. Этот параметр показывает время без учета накладных расходов.
  • -Xlog:safepoint. Показывает время с накладными расходами.
  • -Xloggc:<file>
  • -XX:+PrintGcDateStamps
  • -XX:+PrintHeapAtGC
  • -XX:+PrintTenuringDistribution

Анализ диагностического вывода:

  • PrintGCStats
  • GChisto
  • VisualVM / VisualGC

Мета информация

Область:: 00 Java разработка
Родитель:: Устройство Java
Источник::
Автор::
Создана:: 2023-11-06

Дополнительные материалы

  1. Сборка мусора в Java.
    1. В общих чертах о сборке мусора.
  2. Алексей Шипилёв — Shenandoah.
    1. Подробно рассказаны алгоритмы маркировки и копирования объектов.
  3. Заметки Гусев Влад
  4. Есть какая-то книга GC Handbook

Дочерние заметки