Fabian Zeindl
Fabian Zeindl

Reputation: 5988

When does WeakReference#get() start returning null?

I want to use WeakReferences as part of an (android) bitmap-cache to be able to check when a bitmap isn't used anymore.

My cache has a maximum-size that is smaller than the Java heap-space. When a new bitmap would overflow the cache, it should let go of bitmaps that aren't needed anymore.

My question: When does the get()-method of a WeakReference return null?

  1. As soon as there are no more strong-references to the object? (and GC hasn't occurred yet)
  2. Or when the GC has run and determined that their are no more strong-references to the object?

If 2. is true than I could run into the situation that my cache could fill up and GC hasn't recently run for some reason.

Then even if I had already let go of references AFTER the last GC run, WeakReference#get() would still return the object and my cache wouldn't clear it out.

Upvotes: 14

Views: 8324

Answers (4)

Pierre Laporte
Pierre Laporte

Reputation: 1215

As stated in the other answers, a WeakReference will return null once the pointed object has no more strong/soft references and the GC has reclaimed memory.

On a more general rule, I don't think Weak/SoftReferences are a good thing in an application. It makes your mix concerns :

  • Your application is about business logic
  • The JVM and Dalvik are about memory management and code optimisation.

When you start to use Weak/Soft references, you introduce memory-managed concerns within your application, which makes it harder to develop/debug/understand.

You might want to have a fixed-size (number of elements or bitmap size) LRU cache instead.

Hope that helps !

Upvotes: -3

Gabe Sechan
Gabe Sechan

Reputation: 93614

The answer is it depends on what version of Android you're using. Somewhere in the 2.3 timeframe, Android changed its handling or weak references. Previously, it deleted them when the GC ran. As of some version of 2.3 (2.3.3?) it started deleting them immediately upon the last strong reference going away. So in modern versions of Android, weak references are useless.

Before this change, weak references were used for caching. They no longer work. The correct way now is to use an LRUCache. If you need to support older versions, use the support library to backport the LRU cache.

After some searching, I think the change was made in 3.0, not 2.3. Still, the solution is the same.

Upvotes: 14

Navin Ilavarasan
Navin Ilavarasan

Reputation: 1271

To cache bitmaps use SoftReference rather than Weak. GC would clear WeakReference as soon as it looses all its Strong and Soft references which might destroy the purpose of caching. SoftReference are cleared only if there is low memory.And it is guaranteed that the GC would be run before throwing a OOME.

Upvotes: 5

Andy Thomas
Andy Thomas

Reputation: 86419

The WeakReference is cleared as soon as the GC has determined that the object is weakly reachable.

This is close to your second case. However, weak reachability requires not just the absence of strong references, but also the absence of soft references.

From the Java package documentation for java.lang.ref:

Soft and weak references are automatically cleared by the collector before being added to the queues with which they are registered, if any.

...

An object is weakly reachable if it is neither strongly nor softly reachable but can be reached by traversing a weak reference. When the weak references to a weakly-reachable object are cleared, the object becomes eligible for finalization.

Upvotes: 5

Related Questions