Що таке 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)]]