Tuesday, February 3, 2009

WeakReference? What is that !

Even though weak references are massively useful features available for fairly long time, I think they are pretty overlooked. ( Yeah, I am pretty bemused by getting multiple "WeakReference? huh! whats that?!" responses on a single day.) So, lets refresh on what weak references are and what they do.

In short, weak references can save you from a lot of problems in case of unintentional object retention. If you don't understand "Unintentional Object Retention" mumbo-jumbo, here is a scenario for you.

Lets say, you need to use gigantic images in your application. But, as you know loading images each time from disk is pretty expensive, you decided to cache it. And as a sane person, you don't want the gigantic images using up a large chunk of memory when there is no reference to it. Now, how can you do that? If you use normal reference to the image ( to place it in vector or hash map or in your custom cache class ), when GC will run, it will find that it has at least a reference to that image and would refrain itself from finalizing and reclaiming the memory. Now what you can do is, keeping some kind of in house count of the references that point to that image and when there is no other reference pointing, you can remove the holding reference from your cache store making it eligible for garbage collection. Is it fun to mimic the garbage collector? Hell, No !

Here comes the mighty weak reference into play. To put simply weak references are not strong enough to force the referent object to remain in memory. Another mumbo-jumbo? Well, lets go into details.

Each ordinary reference in Java is a strong reference. What make them strong is the way they interact with GC. More particularly, if an object is reachable through a chain of strong reference it will not be claimed by GC. So for two ordinary references x and y, the following statement

x = y;

will make sure that the object to which y points would be kept in memory as long as x is reachable.

But, for a weak reference, that is not the case. If all the references to a particular object are weak references ( we call this situation "weakly reachable"), then garbage collector is eligible to claim the object. So if you use WeakReference, like the following

WeakReference<SomeOtherRef> weakReference = new WeakReference(someOtherRef);

you are making sure that garbage collector's reachability has been increased and later you can get the reference by using

weakReference.get();

The point to remember is that it is not enough strong to prevent from garbage collection, so don't surprise if get() all on a sudden, starts returning null.

So, by now you have got what you need for that caching mechanism. In your caching store house, you will use WeakReference so that when there is no other strong references, the gigantic image is gracefully removed by the GC.

Java provides more control over garbage collection by providing PhantomReference, SoftReference, ReferenceQueue and WeakHashMap. But I think I have enough for today, so all these have to wait.

4 comments:

Sihan said...

Fabulous Posting!

shah said...

good one

Piyush Patel said...

Hi,'m Still not convinced with use of Weak-reference in android ? How-to ? seems week ref is cache friendly..

VNOSC said...

Thanks for Siam's posting! It's very useful!
@Piyush: Because of limited memory, I think WeakReference is very useful in programming Android. For example, you would like to build an count-up timer on your screen, so you may use extend TimerTask, Handler class and implement Runnable interface to do. And after interval delayed, the run() method will be executed. If you use normal reference, GC will wait until the upper method finishs running. It will make the memory increase gradually and maybe crash the app at particular time. And if you use WeakReference, whenever you get(), the GC will remove the weak reference at that time, so it ensures your app will not be overflowed.