X
Let's get in touch

Memory leak problem in Java

I think that more-less everybody have by now been burned at least once by some memory leaks in Java. Although it sounds impossible (it is a managed language after all, isn’t it?), that actually happens quite often. The problem is usually with leaky abstractions – we, the developers are lead to belive that we don’t really have to worry about memory – GC is taking care of that stuff, isn’t it? In reality, you actually do have to worry about memory. Even though the garbage collector will free all unreferenced memory chunks, you as a developer have to make sure that no chunks end up being referenced.

Usually, the culprits are either some action listeners that are left hanging, or some references in some long forgotten collections (Singletons really are evil sometimes!).

In our case, it was neither. Here are the symptoms: the application does a whole lot of calculation and uses some tree-like data structures to do the math. We feed it with a lot of data and the memory footprint at one moment in time is ~ 700megs (we’ve got ~ 1G of heap). Then we’re done. And it’s not yet freed. But that’s OK, since GC tends to be lazy. The problem occurs when you want to do the same operation twice – the second time time, JVM runs out of memory.

So, after a couple of days of tracing the leak (my first suspicion was that we had some sort of a leak in our tree-like structure), it can all boil down to this small code snippet:

Here, we create a JDialog instance that has one neat attachment to it – a 4meg worth of empty integer. Set up -Xmx64m for this test case and only after a few runs, you’ll run out of memory. How is it possible that I run out of memory here? There are no collections, all variables are locally scoped – GC should be picking JDialog up after each loop iteration (or at least after a few). However, it seems that this does not occur. The only thing that seems to fix the issue is calling dispose manually like this:

Please note that the tested platform is JVM 1.6.0_19, Windows7 Ultimate (it also happens on XP). Here is what the Java documentation says about dispose:

“Releases all of the native screen resources used by this Window, its subcomponents, and all of its owned children. That is, the resources for these Components will be destroyed, any memory they consume will be returned to the OS, and they will be marked as undisplayable.”

Inspecting heap dumps of both cases revealed that if we don’t explicitly call dispose(), that JDialog (actually, MemoryLeakTest$1 instances) instances remain in memory (I guess Swing has some references to them – we obviously don’t have them) and are not garbage collected. However, doing dispose() seems to have cleaned up the system resources and removed those references in Swing because we can’t see a single dialog instance on the heap anymore. The worst thing here is that it seems that this behaviour is not documented in the documentation (dispose() docs don’t say anything about this – see http://java.sun.com/javase/6/docs/api/java/awt/Window.html#dispose() ).

Leave your comment

We use cookies to help us optimize the website experience. Okay

Learn more about our privacy policy.