Що таке покоління в GC (young, old, metaspace)?
4. Metaspace → встановіть MaxMetaspaceSize 5. Generational ZGC (Java 21+) — найкращий вибір для low-latency додатків на Java 21+. Для старіших версій використовуйте G1.
🟢 Junior Level
GC ділить пам’ять на покоління залежно від того, як довго живуть об’єкти.
Проста аналогія: Уявіть гардероб:
- Young Gen — як новий одяг: швидко зношується і викидається.
- Old Gen — як улюблена куртка: носите роками.
- Metaspace — як викрійки для пошиття одягу. Не сам одяг, а шаблони, за якими він створюється.
Три покоління:
| Покоління | Що зберігається | Як часто GC |
|---|---|---|
| Young Generation | Нові об’єкти | Дуже часто (кожні секунди) |
| Old Generation | Довгоживучі об’єкти | Рідко (кожні хвилини) |
| Metaspace | Метадані класів | При заповненні |
Життєвий цикл об’єкта:
new Object() → Eden (Young)
↓ (пережив GC)
Survivor (Young)
↓ (пережив ще кілька GC)
Old Generation
🟡 Middle Level
Weak Generational Hypothesis
Два спостереження:
- Для більшості веб-додатків ~90-98% об’єктів умирають молодими. Але для задач з великими кешами це не так.
- Об’єкти, що пережили кілька зборок, живуть довго
Наслідок: Різні алгоритми для різних поколінь!
Young Generation
Структура:
Eden (80%) — сюди потрапляють усі нові об'єкти
Survivor S0 (10%) — ті, що вижили
Survivor S1 (10%) — ті, що вижили
Minor GC:
1. Eden + S0 → скануються
2. Живі об'єкти → копіюються в S1
3. Eden і S0 очищуються
4. S0 і S1 міняються ролями
TLAB (Thread Local Allocation Buffer):
Кожному потоку — свій шматок Eden
→ Алокація без синхронізації!
→ Просто зсув вказівника
Old Generation
Сюди потрапляють об'єкти:
1. Переживші 15 зборок (MaxTenuringThreshold)
2. Великі об'єкти (одразу в Old)
3. Коли Survivor переповнений
Full GC — чистить Young + Old
→ Довга пауза (секунди!)
Metaspace
Java 8+: замінив PermGen
→ Знаходиться в Native Memory (поза Heap)
→ Зберігає: класи, методи, константи
→ Росте динамічно
Обмеження:
-XX:MetaspaceSize=256m (початковий поріг)
-XX:MaxMetaspaceSize=512m (максимум)
Card Table оптимізація
Проблема: Minor GC не хоче сканувати весь Old Gen
Рішення: Card Table
→ Old Gen розбитий на картки по 512 байт
→ oldObj.field = youngObj → картка позначається Dirty
→ Minor GC сканує тільки Dirty картки
🔴 Senior Level
TLAB та PLAB
TLAB (Thread Local Allocation Buffer):
→ В Eden, для кожного потоку
→ Pointer bumping: obj_ptr += size
→ 0 синхронізації!
PLAB (Promotion Local Allocation Buffer):
→ Аналог в Old Gen
→ Для копіювання об'єктів, що вижили
→ Уникає contention при просуванні
SATB (Snapshot-At-The-Beginning)
G1 використовує SATB для конкурентного маркування:
→ На початок розмітки: всі живі об'єкти позначені
→ Якщо посилання видаляється під час розмітки → об'єкт все одно живий
→ Floating Garbage: сміття, яке збереться в наступному циклі
Write Barrier для SATB:
→ Перед записом посилання: зберегти старе значення в buffer
→ Buffer обробляється Concurrent Marking
Humongous Objects (G1)
Humongous Objects — об'єкти більше половини розміру регіону G1.
Алокуються напряму в Old Gen, минаючи Young Gen.
Remembered Sets (RSet) — структура даних в G1, яка відстежує
посилання між регіонами. Дозволяє GC не сканувати весь Heap.
Об'єкт > 50% розміру регіону → Humongous
→ Одразу в Old Gen
→ Не копіюється в Young GC
→ Може викликати передчасний GC
Рішення: -XX:G1HeapRegionSize=16m або 32m
Generational ZGC (Java 21+)
ZGC став генераційним!
→ Young та Old покоління
→ Young GC частіше і швидше
→ Old GC рідше
→ -50% CPU overhead vs single-generational
Production Experience
Premature Promotion:
Survivor занадто малий → об'єкти потрапляють в Old Gen
→ Old Gen забивається сміттям
→ Full GC кожні 5 хвилин
Рішення: збільшити SurvivorRatio або Young Gen
Best Practices
- TLAB — алокація без contention
- Card Table — Minor GC не сканує Old Gen
- Humongous → збільште G1HeapRegionSize
- Metaspace → встановіть MaxMetaspaceSize
- Generational ZGC (Java 21+) — найкращий вибір для low-latency додатків на Java 21+. Для старіших версій використовуйте G1.
Резюме для Senior
- Young Gen = copying collector, швидкі збірки
- Old Gen = mark-sweep-compact, повільні збірки
- Metaspace = native memory, ClassLoader lifecycle
- TLAB = lock-free алокація
- Card Table = оптимізація Minor GC
- SATB = concurrent marking в G1
- Humongous = спеціальні регіони для великих об’єктів
- Generational ZGC = майбутнє low-latency GC
🎯 Шпаргалка для інтерв’ю
Обов’язково знати:
- Weak Generational Hypothesis: ~90-98% об’єктів умирають молодими → різні алгоритми для поколінь
- Young Gen: Eden (80%) + Survivor S0 (10%) + Survivor S1 (10%); Minor GC копіює живі між Survivor
- Old Gen: об’єкти, що пережили 15 зборок (MaxTenuringThreshold); Full GC чистить Young + Old
- Metaspace (Java 8+): native memory, зберігає метадані класів; замінив PermGen (був всередині Heap)
- TLAB — приватний буфер потоку в Eden для lock-free алокації (pointer bumping)
- Card Table — бітова карта; при запису
oldObj.field = youngObjкартка позначається Dirty → Minor GC не сканує весь Old Gen - Premature Promotion: Survivor переповнений → об’єкти потрапляють в Old Gen → Full GC
Часті уточнюючі запитання:
- Чому Young Gen — copying, а Old Gen — mark-sweep? — У Young Gen сміття 98%, копіювати 2% ефективно; у Old Gen сміття мало, copying був би дорожчий
- Що таке SATB? — Snapshot-At-The-Beginning: алгоритм G1 для конкурентного маркування; позначає все, що було живе на початок циклу
- Навіщо 2 Survivor області? — Ping-pong: живі об’єкти копіюються S0→S1→S0, збільшуючи age; одна завжди порожня для копіювання
- Чому Metaspace поза Heap? — PermGen (всередині Heap) викликав часті OOM; Metaspace в native memory, росте динамічно
Червоні прапорці (НЕ говорити):
- «Metaspace та PermGen — це одне й те саме» — PermGen всередині Heap (фіксований), Metaspace в native memory (динамічний)
- «Об’єкти потрапляють в Old Gen тільки через age» — Великі об’єкти та переповнення Survivor теж
- «Minor GC чистить Old Gen» — Minor GC тільки Young Gen; Card Table оптимізація, не повне очищення
Пов’язані теми:
- [[4. Що таке Garbage Collection]]
- [[9. Що таке Young Generation]]
- [[10. Що таке Old Generation (Tenured)]]
- [[11. Що таке Metaspace (або PermGen)]]
- [[12. Які алгоритми GC існують]]