Виды ссылок в 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.