Когда WeakReference#get () начнет возвращать null?

Я хочу использовать WeakReferences как часть (android) растрового кэша, чтобы иметь возможность проверить, когда растровое изображение больше не используется.

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

мой вопрос: когда get () - метод a WeakReference вернуть null?

  1. как только больше нет сильных ссылок на объект? (и GC еще не произошло)
  2. или когда GC запустился и определил, что их нет более сильных ссылок на объект?

Если 2. это правда, чем я мог бы столкнуться с ситуацией, что мой кэш может заполнить, и GC недавно не запускался по какой-то причине.

тогда, даже если бы я уже отпустил ссылки после последнего запуска GC,WeakReference#get() все равно вернет объект, и мой кэш не очистит его.

4 ответов


ответ зависит от того, какую версию Android вы используете. Где-то в 2.3 таймфрейме Android изменил свою обработку или слабые ссылки. Ранее он удалял их при запуске GC. Начиная с версии 2.3 (2.3.3?) он начал удалять их сразу же после того, как последняя сильная ссылка ушла. Поэтому в современных версиях Android слабые ссылки бесполезны.

до этого изменения для кэширования использовались слабые ссылки. Они больше не работают. Правильный путь теперь нужно использовать LRUCache. Если необходимо поддерживать более старые версии, используйте библиотеку поддержки для обратного переноса кэша LRU.

после некоторых поисков, я думаю, что изменение было сделано в 3.0, а не 2.3. И все же решение остается тем же.


WeakReference очищается, как только GC определил, что объект слабо достижим.

Это близко к вашему второму делу. Однако слабая достижимость требует не только отсутствия сильных ссылок, но и отсутствия мягких ссылок.

из документации пакета Java для java.ленг.ref:

мягкие и слабые ссылки автоматически очищаются сборщиком перед добавлением в очереди с которыми они зарегистрированы, если таковые имеются.

...

объект слабо достижим, если он не является ни сильно, ни мягко достижимым, но может быть достигнут путем обхода слабой ссылки. Когда слабые ссылки на слабо достижимый объект очищаются, объект получает право на завершение.


для кэширования растровых изображений используйте SoftReference, а не слабый. GC очистит WeakReference, как только он потеряет все свои сильные и мягкие ссылки, которые могут уничтожить цель кэширования. SoftReference очищаются только при недостатке памяти.И гарантируется, что GC будет запущен, прежде чем бросать OOME.


Как указано в других ответах, WeakReference вернет null, как только указанный объект не имеет более сильных / мягких ссылок и GC восстановил память.

по более общему правилу, Я не думаю, что слабые/SoftReferences-хорошая вещь в приложении. Это делает ваши проблемы микс:

  • ваше приложение о бизнес-логике
  • JVM и Dalvik - это управление памятью и код оптимизация.

когда вы начинаете использовать слабые / мягкие ссылки, вы вводите проблемы с управлением памятью в своем приложении, что затрудняет разработку/отладку/понимание.

вместо этого может потребоваться кэш LRU фиксированного размера (количество элементов или размер растрового изображения).

надеюсь, что это поможет !