Garbage Collector

Garbage Collector

Дорогу осилит идущий

Garbage Collector (gc) — механизм JVM, отвечающий за очистку памяти от ненужных объектов (мусора). Именно он позволяет абстрагироваться от прямого управления памятью и работы с деструкторами, актуальных, например, в C++.

Мы упоминали об этом механизме в прошлом уроке, посвященном памяти JVM. Пришло время разобраться подробнее.

Важно понимать, что gc — абсолютно независимый от разработчика механизм (исключая возможность выбора реализации в настройках JVM). Максимум, что мы можем сделать в рамках кодовой базы — рекомендовать gc произвести сборку мусора, используя метод класса System: System.gc(). Однако вызов этого метода не дает гарантии, что Garbage Collector действительно будет запущен. В том числе поэтому в реальных задачах этот метод не используется.

Базовое знакомство с gc предлагаю осуществить на основе видео:


Стратегии сборки мусора

GC использует два подхода, чтобы определить, является объект мусорным:

  1. Подсчет количества ссылок на объект. Если на объект нет ссылок — он считается мусором. Про эту стратегию мы упоминали в предыдущих уроках. Ее недостаток в том, что два (или более) объекта могут ссылаться друг на друга (объект 1 хранится в поле объекта 2 и наоборот). Такая ситуация называется циклической зависимостью (circular dependency). Отсюда истекает актуальность второй стратегии;
  2. Невозможность получить доступ к объекту через корневую точку (root). Корневыми точками считаются локальные и статические переменные. Таким образом, если нет возможности добраться хотя бы до одного объекта, участвующего в циклической зависимости, все объекты в этой циклической зависимости будут признаны мусорными.


Основные понятия

В рамках знакомства с GC стоит ознакомиться со следующими терминами:

  • Stop-the-world — время, на которое GC приостанавливает выполнение программы для сборки мусора. Сама по себе операция сборки мусора достаточно дорогая. В том числе потому что сборка мусора полностью останавливает работу программы. В ряде реализаций GC эта проблема решается, или, по крайней мере, сводится к минимуму;
  • Потребляемые ресурсы – объем RAM (оперативная память) и процессорное время, потребляемое GC во время работы;
  • Пропускная способность – отношение времени работы GC к общему времени работы программы.


Типы (реализации) GC

Существует несколько реализаций Garbage Collector, которые отличаются алгоритмами и/или подходами к очистке мусора. В большинстве случаев, для их понимания нужно достаточно хорошо понимать устройство памяти (точнее, кучи) в JVM.

Итак, реализации GC:

  • Serial GC;
  • Parallel GC;
  • CMS (Concurrent Mark Sweep) GC;
  • G1 (Garbage-First) GC;
  • Epsilon GC.

Рассмотрим основные особенности каждого из них. Не страшно, если вы не запомните весь объем информации. Но советую, хотя бы с большего, уложить в голове информацию о Serial и Epsilon GC.


Serial GC:

  1. При создании объекты помещаются в Eden Space. Часть New (оно же Young) Generation;
  2. Когда он заполняется, запускается быстрая сборка мусора. На этот момент области Survivor Space — S0 и S1 — пусты;
  3. Объекты, пережившие быструю сборку мусора, переносятся в S0;
  4. При заполнении S0 (S1 пуст) запускается повторная сборка мусора;
  5. «Выжившие» объекты из S0 переносятся в S1. Также в него переносятся объекты, пережившие эту сборку в Eden Space (если такие были добавлены после первой сборки). По итогам этой операции S0 окажется пустым;
  6. Последующая сборка мусора будет аналогична п.5, только S1 и S0 поменяются местами;
  7. По итогу нескольких сборок пережившие их объекты перемещаются в Old Generation. Его очистка производится только по факту его заполнения (мы касались этого момента в предыдущем уроке).


Parallel GC отличается от Serial GC только тем, что алгоритм работает в многопоточном режиме.


CMS GC

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

На мой взгляд, подробное описание работы CMS GC в рамках Old Generation сейчас несколько избыточно, по крайней мере, в этом уроке. Для тех, кого заинтересовала тема, предлагаю ознакомиться с официальной документацией. Информация о работе CMS GC (как и о других сборщиках, в т.ч. не освещенных в этой статье) там также присутствует: https://www.oracle.com/technetwork/tutorials/tutorials-1876574.html


G1

Отличается тем, что делит heap не на описанную выше (и в статье о памяти JVM) структуру (хотя результат с точки зрения логики будет похож), а на несколько областей равного размера, получая в итоге несколько областей Eden Space, несколько Survivor Space и несколько Old Generation. В итоге получается не более 2048 областей памяти.

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

В рамках сборок мусора приложение останавливается.


Epsilon GC

Эта реализация Garbage Collector добавилась в Java 11. Она характерна тем, что не занимается сборкой мусора. GC пометит мусорные объекты, но не будет тратить усилий на их удаление. Это может быть полезно для небольших приложений, в которых существует уверенность в том, что heap не будет переполнен (в силу небольшого количества объектов), соответственно, издержки на его очистку избыточны. Таким образом, производительность приложения увеличивается за счет сокращения расходов оперативной памяти и процессорного времени на работу GC.


На сегодня все!

Я понимаю, что информации много и осознать ее с первого раза не получится. Но есть и плюс: необходимости помнить все подробности реализации различных GC нет необходимости:)


Если что-то непонятно или не получается – welcome в комменты к посту или в лс:)

Канал: https://t.me/+relA0-qlUYAxZjI6

Мой тг: https://t.me/ironicMotherfucker

 

Дорогу осилит идущий!

Report Page