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