В чем разница между soft reference и phantom reference в Java?
Что проверяют
Знаете ли вы, как сборщик мусора в JVM обходится с разными уровнями достижимости и зачем они нужны на практике. Почти всегда следом спрашивают про WeakReference и про то, чем Cleaner заменил finalize().
Как отвечать
В java.lang.ref четыре уровня силы ссылок: strong, soft, weak, phantom. Soft и phantom различаются тем, когда ссылку очищают и что можно получить через get():
SoftReference:get()возвращает объект, пока GC его не убрал. Очищают такие ссылки при нехватке памяти, и спецификация гарантирует, что это произойдёт доOutOfMemoryError. В HotSpot срок их жизни зависит от свободной кучи и флага-XX:SoftRefLRUPolicyMSPerMB;PhantomReference:get()всегда возвращаетnull, достать объект через неё нельзя. Смысл вReferenceQueue: когда объект становится фантомно достижимым, ссылка попадает в очередь, и вы узнаёте, что пора освободить связанный ресурс, например нативную память или файловый дескриптор. Начиная с Java 9 такие ссылки очищаются автоматически при постановке в очередь.
Итог для ответа: soft нужна, чтобы подольше подержать объект, phantom нужна, чтобы узнать о его смерти и прибрать за ним.
Сильный ответ упоминает java.lang.ref.Cleaner из Java 9. Это готовая обёртка над фантомными ссылками и штатная замена finalize(), который в Java 18 пометили к удалению (JEP 421). Вы регистрируете объект и Runnable очистки, а поток Cleaner выполнит его после сборки.
Про кэш на soft-ссылках стоит сказать честно: на больших кучах он ведёт себя непредсказуемо и нагружает GC. На практике берут кэш с явным лимитом, например Caffeine с maximumSize.
Где спотыкаются
Говорят, что phantom-ссылка указывает на уже удалённый объект. Точнее так: объект уже недостижим и воскресить его нельзя, а память освобождается после того, как ссылка обработана.
Путают soft и weak. Weak-ссылку очистят на ближайшей сборке, если сильных ссылок не осталось, а soft живёт до нехватки памяти.
Передают в Cleaner лямбду, которая захватывает сам объект. Тогда он навсегда остаётся достижимым, и очистка не выполнится никогда.