Что такое G1 GC?
G1 заменил Parallel GC как сборщик по умолчанию, потому что даёт предсказуемые паузы. Название «Garbage First» означает: сначала собираем регионы, где больше всего мусора (макси...
🟢 Junior Level
G1 (Garbage First) — сборщик мусора по умолчанию в Java (с Java 9).
G1 заменил Parallel GC как сборщик по умолчанию, потому что даёт предсказуемые паузы. Название «Garbage First» означает: сначала собираем регионы, где больше всего мусора (максимальная эффективность за цикл).
Главная идея: Делит Heap на регионы и собирает в первую очередь самые “загрязнённые”.
Простая аналогия: Уборка в доме — сначала убираете самые грязные комнаты, а не весь дом сразу.
Преимущества:
- Предсказуемые паузы (настраиваются)
- Хорошо работает на Heap от 4 ГБ до десятков ГБ. Выше 32 ГБ отключаются Compressed OOPs — это влияет на все GC, не только G1.
- Баланс между скоростью и паузами
🟡 Middle Level
Регионы G1
Heap разбит на 2048 регионов (1-32 МБ каждый)
Типы регионов:
Eden — новые объекты
Survivor — выжившие
Old — долгоживущие
Humongous — большие объекты (> 50% региона)
Free — свободные
Remembered Sets (RSet)
Каждый регион хранит: какие ДРУГИЕ регионы на него ссылаются
Зачем:
→ При Young GC не нужно сканировать весь Old Gen
→ Сканируются только регионы с ссылками на Young
Remembered Sets (RSet) — структура данных для каждого региона,
которая отслеживает входящие ссылки из ДРУГИХ регионов.
Позволяет G1 не сканировать весь Heap.
Цикл работы
1. Young GC (STW) — копирование молодых объектов
2. Concurrent Marking — фоновая разметка Old Gen
3. Mixed GC — Young + самые грязные регионы Old
Цель: уложиться в MaxGCPauseMillis
Тюнинг
-XX:MaxGCPauseMillis=200 # Целевая пауза
-XX:InitiatingHeapOccupancyPercent=45 # Порог Old GC
🔴 Senior Level
Collection Set (CSet)
Набор регионов для очистки в текущем цикле
Collection Set (CSet) — набор регионов, выбранных для сборки
в текущем цикле. G1 выбирает регионы с наибольшим количеством мусора.
Young GC:
→ CSet = все Young регионы
Mixed GC:
→ CSet = Young + самые грязные Old регионы
→ G1 выбирает, чтобы уложиться в MaxGCPauseMillis
Evacuation Failure
При копировании живых объектов нет места в целевых регионах
→ To-space exhausted
→ Full GC (STW!)
Evacuation Failure (To-space exhausted) — когда G1 не хватает
места для копирования живых объектов. Fallback к Full GC —
долгая пауза.
Причины:
- Фрагментация
- Слишком много живых объектов
Решение: увеличить Heap или уменьшить MaxGCPauseMillis
String Deduplication
-XX:+UseStringDeduplication
G1 находит одинаковые char[] в разных String
→ Схлопывает в одну ссылку
→ Экономия 5-10% Heap
Работает только для String, созданных через new String() или конкатенацию.
Строки из пула литералов уже дедуплицированы. Наибольший эффект для
приложений с большим количеством одинаковых строк.
Generational ZGC vs G1
G1: паузы 20-200 мс, хороший throughput
ZGC: паузы < 1 мс, -5-10% throughput
Выбор: SLA < 10 мс → ZGC, иначе G1
Generational ZGC требует Java 21+. На Java 17 используйте G1.
Best Practices
- Не фиксируйте -Xmn для G1 (теряет адаптивность)
- MaxGCPauseMillis не ставьте слишком низко (< 50 мс)
- IHOP настройте под ваш Promotion Rate
- Humongous → увеличьте G1HeapRegionSize
- String Deduplication включите для экономии памяти
- Мониторьте To-space exhausted
Резюме для Senior
- G1 = региональный, адаптивный GC
- RSet = оптимизация Young GC
- CSet = выбирает самые грязные регионы
- SATB = concurrent marking алгоритм
- Evacuation Failure = худший сценарий
- Не фиксируйте Young Gen — G1 адаптивен
- MaxGCPauseMillis = главный рычаг настройки
🎯 Шпаргалка для интервью
Обязательно знать:
- G1 делит Heap на 2048 регионов (1-32 МБ); типы: Eden, Survivor, Old, Humongous, Free
- RSet (Remembered Set): каждый регион хранит, какие другие регионы на него ссылаются → Young GC не сканирует весь Heap
- CSet (Collection Set): регионы, выбранные для сборки в текущем цикле; G1 выбирает самые «грязные»
- Цикл G1: Young GC (STW) → Concurrent Marking → Mixed GC (Young + грязные Old регионы)
- Evacuation Failure (To-space exhausted): нет места для копирования живых → Full GC (STW!)
- SATB (Snapshot-At-The-Beginning): concurrent marking; Floating Garbage — объекты, ставшие мусором после snapshot
- String Deduplication (
-XX:+UseStringDeduplication): G1 схлопывает одинаковыеchar[]в String → экономия 5-10% Heap
Частые уточняющие вопросы:
- Почему нельзя ставить MaxGCPauseMillis слишком низко (< 50 мс)? — G1 не сможет уложиться → Evacuation Failure → Full GC
- Что такое IHOP (InitiatingHeapOccupancyPercent)? — Порог Old Gen (по умолчанию 45%), при котором G1 начинает Concurrent Marking; настройте под ваш Promotion Rate
- Что делать с Humongous Objects? — Увеличьте
-XX:G1HeapRegionSize(например, 16м или 32м), чтобы объекты не считались Humongous - Почему не фиксируется
-Xmnдля G1? — G1 адаптивно меняет Young Gen для достижения MaxGCPauseMillis; фиксация ломает адаптивность
Красные флаги (НЕ говорить):
- «G1 сканирует весь Old Gen при Young GC» — RSet оптимизация: сканируются только регионы с ссылками на Young
- «Поставлю MaxGCPauseMillis=10 мс для максимальной скорости» — G1 не сможет уложиться → To-space exhausted → Full GC
- «String Deduplication экономит память на строках из String Pool» — работает только для
new String()и конкатенации; строки из пула уже дедуплицированы
Связанные темы:
- [[8. Что такое поколения в GC (young, old, metaspace)]]
- [[12. Какие алгоритмы GC существуют]]
- [[14. Что такое ZGC]]
- [[16. Что такое stop-the-world]]
- [[10. Что такое Old Generation (Tenured)]]