Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do I have a JAXB classloader leak

I have an application deployed on Glassfish. Over time the number of loaded classes climbs into the millions and my permgen seems to rise.

To help troubleshoot I added the following to my jvm arguments. -XX:+PrintGCDetails -XX:+TraceClassUnloading -XX:+TraceClassLoading

Now when watching the output, I see the same classes being loaded over and over again. Basically every time a web service is called and JAXB is used to process the xml.

[Loaded com.strikeiron.ZIPCodesInRadius$JaxbAccessorF_userID from JVM_DefineClass] [Loaded com.strikeiron.ZIPCodesInRadius$JaxbAccessorF_userID from JVM_DefineClass]

Does this indicate a leak? If so how do I resolve it?

like image 365
Preston Avatar asked Jul 15 '10 19:07

Preston


People also ask

How do you know if a Classloader is leaking?

To identify such a leak, un-deploy your application and then trigger a full heap dump (make sure to trigger a GC before that). Then check if you can find any of your application objects in the dump. If so, follow their references to their root, and you will find the cause of your classloader leak.

What is Classloader leak?

To leak a classloader it's enough to leave a reference to any object, created from a class, loaded by that classloader. Even if that object seems completely harmless (e.g. doesn't have a single field), it will still hold on to its classloader and all the application state.


2 Answers

I found a similar thread that was describing the same problem I was having. http://forums.java.net/jive/thread.jspa?threadID=53362

I also found a bug at https://github.com/javaee/jaxb-v2/issues/581

Basically, the problem was that I was doing a new JAXBContext("your.class.xsd") every time my bean was invoked. According to the bug "Calling JAXBContext.newInstance(...) implies reloading of everything since either the current or the specified class loader is to be (re-)used."

The solution was to create a singleton which worked great.

public enum JAXBContextSingleton {

INSTANCE("your.class.xsd");
private JAXBContext context;

JAXBContextSingleton(String classToCreate) {
    try {
        this.context = JAXBContext.newInstance(classToCreate);
    } catch (JAXBException ex) {
        throw new IllegalStateException("Unbale to create JAXBContextSingleton");
    }
}

public JAXBContext getContext(){
    return context;
}

}

And to use the singleton

JAXBContext context = JAXBContextSingleton.INSTANCE.getContext();
like image 196
Preston Avatar answered Sep 19 '22 21:09

Preston


This is one of the reasons why I stay away from JAXB. I'd rather write classes to marshal and unmarshal that implement javax.xml.bind.Marshaller and javax.xml.bindUnmarshaller, respectively. I write them once and they're done. None of that reflection and dynamic class generation.

like image 31
duffymo Avatar answered Sep 19 '22 21:09

duffymo