Garbage collector and memory leaks

Why to talk about memory leaks in Java? You who do not know the answer, consider following scenerio that is likely to happen to those, who do not know the answer on previous question ;-)

You have your uber-object A that you're using quite frequently and you need it to listen on some events. Great - let's create an anonymous object B inside your object and hook it to whatever event E you want. Okey, program continues, everything is fine. Well, everything has an end, so is the usefullnes of your uber-object A. You're in Java, you just drop the reference onto the uber-object A with hope that GC will clean the mess after you … Your hope is false… there is that little devil - anonymous listener B - that is keeping the reference to the uber-object A and the 'event queue' of E that is holding the reference to that anonymous object B. So the uber-objet A is still strongly reachable. Damn… we're losing memory here! Not mentioning the mess the uber-object A may still cause.

So what is the answer? Weak / Phantom references… is that the salvation? If you are disciplined enough and have a great foresight. So it's likely not, but close enough :-)

Useful links

Follow the next link and read about different types of object reachability in Java.

Here is a tutorial for uncovering the memory leaks using NetBeans profiler.

Test in java

FIXME - outdated - Download ListenerTest.zip (Eclipse project) and execute it's only class ListenerProblems.java … it will run a simple test using weak / strong references on the anonymous listener. It prints a lot of informations, read them carefully. Simply it shows that if you register anonymous listener from within the object A and you cut the reference to that object A it won't be gc()ed.

Classic mistake when working with WeakReference

Note that WeakReference works as a wrapper. Here is a little example.

 MyClass obj = new MyClass();
 WeakReference<MyClass> objReference = new WeakReference<MyClass>(obj);
 // let's call a method!
 objReference.get().callMySuperMethod()

Even though the last row may seem fine, it's not! This is the straight way to hell because we're dealing with WeakReference, so the get() may return null! Okey let's fix it.

 if (objReference.get() != null) 
     objReference.get().callMySuperMethod();

Better? No, it's not. Consider this simple scenerio. The condition is evaluated but before we can call our super method the gc() is called and garbage collects the reference, NullPointerException is around the corner.

The correct way of working with WeakReference:

    MyClass obj = objReference.get();
    if (obj != null) {
        obj.callMySuperMethod();
        obj = null;
    }

Notice the last row of the then-branch … obj = null, notice that by getting the reference from within objReference we've created a strong reference onto the object inside WeakReference. Therefore we should discard it as soon as possible allowing referenced object to be gc()ed as soon as possible.

FIXME Currently this is a stub (not a guideline at all), it would be cool to consitently extend this topic.

guidelines/memory_leaks.txt · Last modified: 2013/01/23 15:15 by jakub.gemrot