В чем разница soft и weak ссылок в управлении памятью
Что проверяют
Знаете ли вы иерархию достижимости объектов в JVM и умеете ли применить её на Android, а не только пересказать определения. Следом обычно спрашивают, чем вы сами кешируете данные и как ловите утечки Activity.
Как отвечать
Ссылки отличаются тем, насколько сильно удерживают объект от сборщика мусора:
- strong: обычная ссылка, пока она есть, объект не соберут;
- soft (
SoftReference): объект собирается, когда памяти становится мало. Спецификация гарантирует одно: все soft-ссылки будут очищены до того, как JVM броситOutOfMemoryError. Когда именно, решает сборщик; - weak (
WeakReference): объект собирается на ближайшей сборке, как только на него не осталось сильных и мягких ссылок, независимо от объёма свободной памяти; - phantom (
PhantomReference):get()всегда возвращаетnull, нужна только чтобы узнать о сборке черезReferenceQueue.
Дальше практика на Android. Weak-ссылки применяют, когда долгоживущий объект не должен продлевать жизнь короткоживущему: WeakReference<Activity> внутри Handler или колбэка, WeakHashMap со слабыми ключами. На этом же механизме построен LeakCanary: он держит уничтоженную Activity через WeakReference с ReferenceQueue и, если после сборки ссылка не очистилась, сообщает об утечке.
Про soft-ссылки важно сказать прямо: документация Android не советует строить на них кеш. ART не знает, какие объекты вам дороже, и может очистить всё сразу или держать лишнее. Для кеша берут LruCache с явным лимитом, а картинки отдают Coil или Glide.
Где спотыкаются
Говорят, что weak-объект удаляется «сразу». Он удаляется на ближайшей сборке мусора, момент которой вы не контролируете, поэтому код должен быть готов к null в любой момент.
Дважды вызывают get(): сначала проверяют на null, потом берут значение. Между вызовами объект может исчезнуть. Правильно сохранить результат в локальную переменную, и она удержит объект, пока нужна.
Лечат утечку слабой ссылкой вместо правильного жизненного цикла. Если слушатель можно отписать в onDestroy или завязать на lifecycleScope, это надёжнее, чем WeakReference, которая лишь маскирует проблему.