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.
- Different java references, read about weak / phantom references and how GC works with them
- Soft references, more info
- Weak references, more info
- Phantom references, more info
Here is a tutorial for uncovering the memory leaks using NetBeans profiler.
- Using NetBeans profiler to uncover memory leaks
Test in java
- 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.
Currently this is a stub (not a guideline at all), it would be cool to consitently extend this topic.