Получить доступ

GC: поколения и продвижение объектов

Гипотеза о поколениях, Eden и Survivor, minor GC через копирование, tenuring и преждевременное продвижение.

Зачем GC и что такое «мусор»

Сборщик мусора автоматически освобождает объекты в куче, до которых больше нельзя добраться по ссылкам от корней (GC roots). «Мусор» — это недостижимые объекты, а не «ненужные»: достижимый, но забытый объект (например, оставленный в статической коллекции) не соберётся — это и есть утечка в Java.

Автоматизация убирает ручной free и целый класс ошибок (use-after-free, double-free), но переносит цену в паузы и накладные расходы сборки.

Гипотеза о поколениях

Эмпирический факт: подавляющее большинство объектов умирает молодыми, а пережившие первые сборки живут долго (weak generational hypothesis). Из неё следует выгодная стратегия: разделить кучу на молодое и старое поколения и собирать молодое часто и дёшево.

Так сборщик концентрирует усилия там, где мусора больше всего, и редко трогает долгоживущие объекты.

Молодое поколение: Eden и Survivor

Молодое поколение делится на Eden и два Survivor-пространства (S0, S1). Новые объекты создаются в Eden. Когда Eden заполняется, срабатывает minor GC: живые объекты Eden и активного Survivor копируются в другой Survivor.

Это copying collection: копируются только живые объекты, поэтому пауза пропорциональна числу выживших, а не мёртвых; Eden и опустевший Survivor затем очищаются целиком. Так большинство короткоживущих объектов исчезает, ни разу не покинув young, а заодно решается фрагментация — выжившие укладываются плотно.

$ java -Xlog:gc -jar app.jar

[0.412s][info][gc] GC(0) Pause Young (Normal) (G1 Evacuation Pause) 512M->8M(2048M) 4.101ms
[1.930s][info][gc] GC(1) Pause Young (Normal) (G1 Evacuation Pause) 520M->12M(2048M) 3.884ms

# 512M->8M: занято до сборки -> после. Почти всё оказалось мусором,
# сборка заняла 4 мс — работа пропорциональна выжившим, а не всей куче.
Схема поколений кучи: молодое поколение (Eden и Survivor S0/S1) и старое поколение со стрелками продвижения объектов по мере старения.
Объекты создаются в Eden, переживают сборки в областях Survivor и со временем продвигаются в старое поколение.

Продвижение и tenuring

У каждого объекта есть счётчик пережитых minor GC (хранится в заголовке). Пережив порог (tenuring threshold), объект продвигается (promotion) в старое поколение.

Если Survivor переполняется, происходит преждевременное продвижение (premature promotion): молодые объекты «протекают» в old, провоцируя дорогие сборки старого поколения. Маленький Survivor → ранний promotion → частые full GC — классическая причина проблем с паузами.

Старое поколение и full GC

В старом поколении живут долгожители. Его сборка (major GC) реже, но дороже. Full GC затрагивает всю кучу (и часто metaspace) и обычно даёт самые длинные паузы — частые full GC почти всегда симптом проблемы (утечка, premature promotion, нехватка кучи).

Современные региональные сборщики (G1) размывают жёсткое деление на непрерывные поколения, но логика «young собирается часто, old редко» сохраняется.

Как отвечать на собеседовании

Свяжите гипотезу о поколениях с разделением кучи, объясните minor GC как copying collection (копируем живых, пауза ~ числу выживших, заодно нет фрагментации), и разберите tenuring и premature promotion как причину частых full GC. Подчеркните: GC собирает недостижимое, а утечка — это достижимый, но забытый объект.

Вопросы по теме

Читайте также

Закрытая бета

Знать тему — половина дела

На живом собеседовании sotto слышит вопрос интервьюера и показывает короткий ответ и план. Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем