Що таке reachability в контексті GC?
4. Phantom — об'єкт майже видалений 5. Unreachable — сміття
🟢 Junior Level
Reachability (Досяжність) — статус об’єкта: чи можна до нього дістатися з коду.
5 рівнів:
- Strong — звичайне посилання (
Object obj = new Object()) - Soft — видаляється при нестачі пам’яті
- Weak — видаляється при наступному збиранні
- Phantom — об’єкт майже видалений
- Unreachable — сміття
🟡 Middle Level
Типи посилань
| Тип | Коли видаляється | Застосування |
|---|---|---|
| Strong | Ніколи | Бізнес-об’єкти |
| Soft | При загрозі OOM | Кеші |
| Weak | При наступному GC | WeakHashMap |
| Phantom | Після фіналізації | Очищення ресурсів |
// Soft Reference
SoftReference<Data> ref = new SoftReference<>(data);
Data cached = ref.get(); // null, якщо GC видалив
// Weak Reference
WeakReference<User> ref = new WeakReference<>(user);
// GC видалить при найближчому збиранні
// Phantom Reference
PhantomReference<Resource> ref = new PhantomReference<>(resource, queue);
// get() завжди null! Тільки для відстеження видалення
Cleaner (Java 9+)
// Заміна finalize()
Cleaner cleaner = Cleaner.create();
Cleanable cleanable = cleaner.register(obj, () -> {
nativeFree(handle); // Очищення
// handle — це native pointer (long), отриманий з JNI/MemorySegment.
// Cleaner дозволяє звільнити native-пам'ять, яку GC не контролює.
});
cleanable.clean(); // Ручне очищення
🔴 Senior Level
SoftReference формула
JVM очищає, коли:
поточний_час - last_access < вільна_пам'ять × SoftRefLRUPolicyMSPerMB
За замовчуванням: 1000 мс на кожен МБ
→ «9 годин» — теоретичний максимум при 32 ГБ free і default policy.
→ Насправді SoftReferences очищуються значно раніше під навантаженням.
Налаштування: -XX:SoftRefLRUPolicyMSPerMB=100
Reference Handler Thread
Високопріоритетний системний потік:
1. GC виявляє зміну досяжності
2. Об'єкт → Pending List
3. Reference Handler → ReferenceQueue
4. Додаток опитує чергу
→ Асинхронно, не блокує GC
Resurrection (Воскресіння)
// ❌ У finalize() можна воскресити об'єкт
protected void finalize() {
GlobalCache.add(this); // Strong посилання → об'єкт живий!
}
// Cleaner не може воскресити:
// → Лямбда НЕ має посилання на this
Best Practices
- Strong = бізнес-логіка
- Soft = кеші (налаштуйте SoftRefLRUPolicyMSPerMB)
- Weak = метадані
- Phantom/Cleaner = нативні ресурси
- Уникайте resurrection
- ReferenceQueue для моніторингу
Резюме для Senior
- 5 рівнів досяжності
- Soft = кеші, очищення при загрозі OOM
- Weak = наступне збирання
- Phantom = відстеження видалення
- Cleaner = заміна finalize()
- Reference Handler = асинхронний потік
- Resurrection = архітектурне зло
🎯 Шпаргалка для інтерв’ю
Обов’язково знати:
- 5 рівнів досяжності: Strong (звичайне посилання), Soft (при нестачі пам’яті), Weak (при наступному GC), Phantom (після фіналізації), Unreachable (сміття)
- SoftReference: для кешів; формула очищення:
free_memory × SoftRefLRUPolicyMSPerMB(за замовчуванням 1000 мс/МБ); на 32 ГБ — теоретично 9 годин, але на практиці значно раніше - WeakReference: для WeakHashMap, метаданих; очищується при НАСТУПНОМУ збиранні (не чекає нестачі пам’яті)
- PhantomReference:
get()завжди null; використовується ТІЛЬКИ з ReferenceQueue для відстеження видалення; замінюєfinalize() - Cleaner (Java 9+): заміна
finalize(); лямбда НЕ має посилання на this → немає «воскресіння»;cleanable.clean()для ручного очищення - Reference Handler: високопріоритетний системний потік; GC → Pending List → Reference Handler → ReferenceQueue → додаток опитує
- Resurrection: у
finalize()можна присвоїтиthisстатичному полю → об’єкт «воскресне»; Cleaner не може воскресити
Часті уточнюючі запитання:
- Чому SoftReference на 32 ГБ може жити годинами? — Формула: 32 ГБ × 1000 мс/МБ = 9 годин; налаштування:
-XX:SoftRefLRUPolicyMSPerMB=100→ агресивніше - Чому PhantomReference.get() завжди null? — Спеціально designed: об’єкт майже видалений, посилання вже не потрібне; тільки ReferenceQueue для відстеження
- Чим Cleaner кращий за finalize()? — Лямбда Cleaner НЕ має посилання на this → неможливо воскресити об’єкт; finalize() може присвоїти
this→ resurrection - Чому Reference Handler асинхронний? — Не блокує GC; GC поміщає об’єкт у Pending List; Reference Handler обробляє пізніше → додаток опитує ReferenceQueue
Червоні прапорці (НЕ говорити):
- «SoftReference очищується одразу після видалення Strong посилання» — очищується ТІЛЬКИ при загрозі OOM
- «PhantomReference дозволяє отримати об’єкт» —
get()завжди null; тільки ReferenceQueue - «finalize() — нормальний спосіб очищення ресурсів» — deprecated (Java 9+), непередбачуваний, може воскресити об’єкт
Пов’язані теми:
- [[5. Коли об’єкт стає кандидатом на видалення GC]]
- [[25. Що таке GC roots]]
- [[27. Чи можна вручну викликати GC]]
- [[6. Що таке витік пам’яті в Java]]
- [[4. Що таке Garbage Collection]]