I got quite a few comments on my last blog (How to fix the dreaded "java.lang.OutOfMemoryError: PermGen space" exception (classloader leaks)). Apparently more people have been struggling with this problem.
Why bring this up? What's the news? Edward Chou continued to
explore options to diagnose classloader leaks. First of all, he
explored how to generate a list of orphaned classloaders with jhat. An orphaned classloader
is a classloader that is not referenced by any object directly but
cannot be garbage collected. The thinking behind this is that programs
that create classloaders (e.g. application servers) do maintain
references to them. So if there's a classloader that is no longer directly referenced, this
classloader is probably a leak. Read about it on his blog (Find
Still we were not satisfied: when examining some memory dumps from
code that we were not familiar with, we explored yet some other options
to diagnose classloader leaks: duplicate classes and duplicate
classloaders. Let me explain.
Let's say that your application has a com.xyz.Controller class. If
you find many instances of this
class object, you likely have a classloader leak. Note the
phrase "instances of this class object".
What I mean by this: the class com.xyz.Controller
is loaded multiple times, i.e. multiple instances of the com.xyz.Controller.class
are present. You can use jhat
to run this query: simply list all instances of java.lang.Class.
Edward modified jhat
to generate a list of all classloader instances that have an identical
set of classes that it loaded. Typically there's no reason why someone
would create two classloader instances and load exactly the same set of
classes into them. If you find any in your memory dump, you should get
suspicious and take a closer look. Monitor Edward's blog for more
details on this.
One more thing: Edward found out that the method java.lang.String.intern()
allocates memory in PermGen space. So if your application frequently
uses this method with different strings, watch out. Fortunately these
strings are subject to garbage collection. But if your application
holds references to these strings, thereby making garbage collection
impossible, your application may cause the dreaded "java.lang.OutOfMemoryError: PermGen
space" exception. No classloaders involved this time.