Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the benefits to using WeakReferences?

I have some memory leaks in my app. They all originate around a specific view cluster that I have spent a loooot of time tweaking and trying to reduce a much contextual passing as possible. This leads me to believe that bitmaps used in the cluster are the issue. So I was thinking to use WeakReferences for all references to the bitmaps used by the views. I have never used a WeakReference and am not sure if this is a good application. Can any body provide an helpful pointers or tips?

like image 942
ahodder Avatar asked May 24 '11 20:05

ahodder


People also ask

What is the purpose of a weak reference?

A weak reference permits the garbage collector to collect the object while still allowing the application to access the object. A weak reference is valid only during the indeterminate amount of time until the object is collected when no strong references exist.

Should I use weak references?

A developer should use long weak references only when necessary because the object is unpredictable after finalization. We should avoid using weak references to small objects because the pointer itself may be as large or larger.

What is the difference between strong and weak references C#?

The difference between a weak and a strong reference to an object is that while the former still allows the garbage collector to reclaim the memory occupied by that object, a strong reference to an object doesn't allow the garbage collector to reclaim the memory occupied by that object if the object is reachable.

What is weak reference in Python?

A weak reference to an object is not enough to keep the object alive: when the only remaining references to a referent are weak references, garbage collection is free to destroy the referent and reuse its memory for something else.


3 Answers

So I was thinking to use WeakReferences for all references to the bitmaps used by the views. I have never used a WeakReference and am not sure if this is a good application. Can any body provide an helpful pointers or tips?

Be careful, this is dangerous in your case. The GC could get rid of all your bitmaps while your application may still need them.

The key issue about WeakReference is to understand the difference with hard references. If there is no more hard reference to a bitmap in your application, then the GC is allowed to atomically remove the object from memory and all existing weak reference will instantaneously point to null. In your case, you CANNOT use weak references all over your code.

Here is an idea of the solution. Create a container object that will keep weak references (only) to all your bitmaps. Your views should always reference bitmaps with hard references only. When a view creates a bitmap, it should register it in the container object. When it wants to use a view, it should obtain a hard reference from the container.

Like that, if no views is referring to a bitmap, then the GC will collect the object without side effects for views, since none has a hard reference to it. When using weakly referenced objects, it is good practice to explicitly set hard references to null when you don't need the object anymore.

Addition

Here is a quick implementation of the solution (just to give an idea):

public class BitmapContainer {

    public static class Bitmap {
        private final long id;
        public Bitmap(long id) { this.id = id; }
        public long getId() { return id; }
        public void draw() { };
    }

    WeakHashMap<Bitmap, WeakReference<Bitmap>> myBitmaps
        = new WeakHashMap<Bitmap, WeakReference<Bitmap>>();

    public void registerBitMap(Bitmap bm) {

        if ( bm == null ) throw new NullPointerException();

        WeakReference<Bitmap> wr = new WeakReference<Bitmap>(bm);
        myBitmaps.put(bm, wr);

    }

    /** Method returns null if bitmap not available */
    public Bitmap getBitMap(long id) {

        for ( Bitmap item : myBitmaps.keySet() ) {
            if ( item != null) {
                if ( item.getId() == id ) {
                    return item;
                }
            }
        }

        return null;

    }

}
like image 69
Jérôme Verstrynge Avatar answered Nov 18 '22 01:11

Jérôme Verstrynge


The most straight-forward use of weak references I can think of is a cache. You want to add objects to a cache, but if there are no references to the object in the rest of the VM, you want the object to get GC'ed without having to go back and remove it from the cache yourself. Weak references achieve this. You add a weak reference to the object in your cache. When the cache is the only thing that refers to your object, it is eligible for GC. Attempts to use the weak reference after the object is GC'ed result in an exception.

Strictly speaking, an object is eligible for GC when no strong references to it remain (i.e. whether or not any weak references to it exist).

Based on your description of your situation, it is not clear that weak references will help you. But if you are facing a situation where you need to intentionally clear references to objects that are no longer needed, then weak references may be the solution. You just have to be sure that when only weak references remain, it really is OK to get rid of the object.

like image 27
wberry Avatar answered Nov 17 '22 23:11

wberry


A need for WeakReferences comes from a scenario in which you need to maintain metadata about an object for which you do not control.

A contrived example would be String, it is final, and we cannot extend it, but if we would like to maintain some extra data about a specific String instance, we would likely use a Map implementation that would hold this metadata. For this example, I will suggest we want to keep the length of the string as our metadata (yes I know that the String object already has a public length property). So we would create a Map like this:

Map<String, Integer> stringLengths = new HashMap<String, Integer>();

Assume that we might populate this map in some method, and not know when we are done with the data, so we cannot explicitly remove the entries. As we populate this map, which will never be unpopulated, our references will be held onto forever. If the application runs for a long time, there is a good chance that we will run into an OutOfMemoryError.

A solution to this would be to use a WeakHashMap implementation.

Map<String, Integer> stringLengths = new WeakHashMap<String, Integer>();

This way, when all (strong) references to the key are gone, the next GC will cause the entry of the WeakHashMap to be removed. (Yes, I understand that String has a special place in the heart of the JVM, but I am assuming that String's are GC'd the same way a normal Object would be in this contrived example)

If this is the approach you are using in your app (storing your Bitmaps in a global map), I think this is definitely something to look into.

like image 28
nicholas.hauschild Avatar answered Nov 18 '22 01:11

nicholas.hauschild