I\'am struggling with unreachable objects in my JVM heap (Java 1.7). As you can see from the picture (all classes on the picture are unreachable), we have more than 74 % objects
There are several aspects in the behaviour you are facing. First and foremost, having unreachable objects inside heap at any given time is perfectly normal. Garbage Collection will clean the unreachable objects during the next run and will clean the heap from them. So, seeing unreachable data structures in heap dump is not evil nor abnormal.
But when facing java.lang.OutOfMemoryError: Java heap space error, these unreachable references should have been cleaned. You can check this via adding -XX:+HeapDumpOnOutOfMemoryError to your startup parameters, triggering heap dump on next OutOfMemoryError generated. When you now crawl this dump, you should not see the unreachable objects, at least not of any significant size.
After understanding this, the underlying problem is still unclear, one of the possible causes can definitely be a heap leak. For this, you can either try to go ahead with the same memory dump gotten during the JVM crash with OutOfMemoryError, or you can make your life easier and attach a Java memory leak detector to find the exact location of the leak in your source code.
This question might be related to this one
Java heap overwhelmed by unreachable objects
I found it as I'm facing the same problem in an IBM JVM 5 runninf on AIX 6.1
The only amount of retained heap that grows consistently between two fullgcs is the unreachable objects, marked, if I'm not wrong, with ROOT as the dominator in Eclipse MAT.
To get these dumps, I configureg the JVM to create a sysdump after a fullgc using the Xdump option (only for IBM JVMs, I think)
Hope this helps, and if anybody knows if the GC verbose log leaves a trace of the unreachable objects that couldn't be cleaned, please let me know!
Carlos
One possibility is that you are overloading the JVM with pathological behavior in finalize()
methods. If you have classes that override Object.finalize()
the JVM has to do a surprising amount of work in order to actually clean them up (and, in turn, clean up all their referenced objects). If you create such objects faster than the garbage collector can process them you'll quickly run into trouble.
This article walks through a pathological finalizer example in detail, but to summarize:
finalize()
method falls out of scope and (conceptually) becomes eligible for GC.finalize()
.Finalizer
thread, which will call .finalize()
on each object in turn. Objects that haven't yet had their turn remain on the heap though they're unreachable.Finalizer
thread this last reference is removed and the object can finally actually be GC'ed. Since the object survived one or more collection rounds it may take some time for the GC to get around to it.If your .finalize()
methods take a particularly long time or if you're creating a large number of such objects the Finalizer
thread can't keep up with the demand and objects will continue to queue up, eventually filling your entire heap.
There are other possible explanations, but over-use of finalize()
is a likely reason. Effective Java Item 7 strongly discourages finalizers:
Finalizers are unpredictable, often dangerous, and generally unnecessary. Their use can cause erratic behavior, poor performance, and portability problems....
Providing a finalizer for a class can, under rare conditions, arbitrarily delay reclamation of its instances.