Как работает Garbage Collector (сборщик мусора) в Java и какие основные типы сборщиков существуют?

«Как работает Garbage Collector (сборщик мусора) в Java и какие основные типы сборщиков существуют?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Принцип работы и поколения Heap: Память кучи (Heap) разделена на поколения, исходя из гипотезы о времени жизни объектов:

  1. Young Generation: Сюда помещаются новые объекты.
    • Eden: Объекты создаются здесь.
    • Survivor Spaces (S0, S1): Сюда перемещаются объекты, пережившие Minor GC.
  2. Old Generation (Tenured): Сюда перемещаются объекты, которые пережили несколько сборок в Young Generation (долгоживущие объекты).
  3. Metaspace (ранее PermGen): Хранит метаданные классов.

Типы сборок:

  • Minor GC: Быстрая сборка, очищающая только Young Generation.
  • Major/Full GC: Сборка мусора во всей куче (Young + Old), обычно более длительная, вызывающая паузы (STW - Stop-The-World).

Основные алгоритмы/сборщики:

  • Serial GC: Однопоточный, для приложений с маленькой кучей.
  • Parallel GC (Throughput Collector): Многопоточный для Minor и Major GC, оптимизирован для пропускной способности.
  • CMS (Concurrent Mark-Sweep): Старался минимизировать паузы, выполняя часть работы конкурентно с приложением. Устарел (deprecated).
  • G1 GC (Garbage-First): Современный сборщик по умолчанию для больших куч. Делит кучу на регионы и собирает те, где больше всего мусора.
  • ZGC / Shenandoah: Сборщики следующего поколения, цель — паузы менее 10 мс даже для терабайтных куч.

Настройка и мониторинг (примеры флагов JVM):

# Включение G1 GC (дефолтный с Java 9+)
-XX:+UseG1GC

# Установка размеров кучи
-Xms512m -Xmx2g

# Логирование работы GC
-XX:+PrintGCDetails -Xlog:gc*:file=gc.log

# Целевая максимальная пауза для G1
-XX:MaxGCPauseMillis=200

Важные практики:

  • Избегайте утечек памяти (например, static коллекции, растущие без очистки, или listeners без отписки).
  • Минимизируйте создание ненужных объектов в горячих циклах.
  • Не вызывайте System.gc() в production-коде — это лишь рекомендация для JVM, которая может нарушить работу выбранного алгоритма GC.