Виды ссылок в Java

Обычная сильная ссылка удерживает объект достижимым. Специальные ссылки из java.lang.ref позволяют GC взаимодействовать с кэшами и внешними ресурсами, но не дают точного времени обработки.

СсылкаКогда referent может быть очищенget()
strongпосле потери достижимости от GC rootsобычный доступ
SoftReferenceпо усмотрению GC, обычно под давлением памятиобъект или null
WeakReferenceкогда объект стал только слабо достижимобъект или null
PhantomReferenceпосле определения фантомной достижимостивсегда null
ReferenceQueue<Object> queue = new ReferenceQueue<>();
Object value = new Object();
WeakReference<Object> reference = new WeakReference<>(value, queue);
 
value = null; // объект теперь может быть собран
Object maybeValue = reference.get(); // результат недетерминирован

ReferenceQueue сообщает, что ссылка перешла в соответствующее состояние. Для PhantomReference очередь — основной канал: referent через get() получить нельзя. Это позволяет связать отдельное описание внешнего ресурса с посмертной очисткой без «воскрешения» объекта.

Где применять

  • WeakHashMap — метаданные, которые не должны продлевать жизнь ключа;
  • weak reference — канонизация/наблюдение при понимании семантики;
  • phantom + queue или Cleaner — резервная очистка низкоуровневого ресурса;
  • soft reference — редко; это плохо управляемый кэш.

Для прикладного кэша лучше явная библиотека с лимитом размера, TTL, статистикой и политикой вытеснения.

Ошибки

  • считать, что System.gc() гарантирует сборку;
  • читать get() дважды: между чтениями GC может очистить referent;
  • забывать хранить сами Reference, из-за чего очередь бесполезна;
  • освобождать обязательный ресурс только через special reference.
Object current = reference.get();
if (current != null) {
    use(current); // сильная локальная ссылка удерживает объект на время вызова
}

На собеседовании

Когда очищается weak reference? Когда referent больше не сильно/мягко достижим и GC обрабатывает слабые ссылки; точное время не гарантируется.

Возвращает ли phantom reference объект? Нет, get() всегда null.

Подходит ли SoftReference для production-кэша? Обычно нет: политика зависит от JVM и плохо контролируется.

Зачем ReferenceQueue? Асинхронно узнать об обработке ссылок и убрать связанные записи/ресурсы.

Связано: Процесс сборки мусора, Finalize, Garbage collector.