Как работает сборка мусора в Java? Какие сборщики вы знаете и чем отличается G1 от ZGC?
Короткий ответ
- GC находит достижимые объекты от GC roots, остальное — мусор
- Поколенческая гипотеза: большинство объектов умирают молодыми
- Minor GC чистит young, full/mixed затрагивает old
- G1 — регионный сборщик по умолчанию, цель — предсказуемые паузы
- ZGC и Shenandoah дают паузы в доли миллисекунды почти независимо от размера кучи
- Stop-the-world паузы есть у всех, вопрос в их длительности
GC автоматически освобождает недостижимые объекты; современные сборщики (G1, ZGC) борются за короткие предсказуемые паузы.
Как сказать вслух
пример ответаСборщик мусора отслеживает объекты, до которых ещё можно добраться по ссылкам от корней — стеков потоков, статических полей. Всё остальное считается мусором и освобождается. Большинство объектов умирают быстро, поэтому куча делится на поколения, и молодое чистится часто и дёшево. По умолчанию сейчас работает G1, а для больших куч и низких задержек берут ZGC — у него паузы меньше миллисекунды.
Подробный ответ
Основной ответ
GC строит граф достижимости от GC roots (стеки потоков, статические поля, JNI-ссылки); недостижимые объекты утилизируются. Поколенческая гипотеза говорит, что большинство объектов короткоживущие, поэтому куча делится на young и old: minor GC копирует выживших между survivor-областями и продвигает долгожителей в old. G1 (по умолчанию) делит кучу на регионы и собирает сначала самые «мусорные», укладываясь в целевую паузу (-XX:MaxGCPauseMillis). ZGC — полностью конкурентный сборщик с цветными указателями и барьерами чтения: паузы субмиллисекундные и почти не зависят от размера кучи; с JDK 21 он поколенческий. Выбор сборщика — компромисс между пропускной способностью, паузами и накладными расходами.
Ключевые моменты
- Достижимость. Мусор — то, что недостижимо от GC roots; подсчёт ссылок в JVM не используется, циклы не проблема.
- G1. Регионный сборщик, балансирует пропускную способность и паузы; хороший дефолт для большинства сервисов.
- ZGC / Shenandoah. Конкурентные low-latency сборщики; платят барьерами и чуть большим CPU за паузы меньше миллисекунды.
- Диагностика. GC-логи (-Xlog:gc*), jstat, JFR — первое, что смотрят при паузах и росте памяти.
Практический контекст
В работе это всплывает, когда сервис «подвисает» под нагрузкой: включают GC-логи и смотрят частоту и длительность пауз, долю full GC. Типичные действия — поднять кучу, убрать лишние аллокации, перейти на ZGC для latency-критичных API. Интервьюер хочет услышать не заучивание флагов, а понимание компромиссов: throughput против пауз и почему full GC в G1 — тревожный сигнал.
Частые ошибки
- Утверждают, что System.gc() гарантированно запускает сборку — это лишь запрос
- Думают, что у ZGC совсем нет stop-the-world пауз — они есть, но очень короткие
- Не отличают minor GC от full GC и не могут объяснить, что такое promotion