Is there any way to speed up the initialization of javax.xml.bind.JAXBContexts with a large (>1000) number of classes? In our XML heavy application the startup time is some 10 minutes and consists mainly of the initialization time of the JAXBContexts. :-(
We are using Sun's JAXB implementation in the JDK 1.5 and the org.jvnet.jaxb2.maven2.maven-jaxb2-plugin for the code generation from XSDs.
Clarification: The problem is not that we have many instances of a JAXBContext with the same contextpaths, but the problem is that the initialization of one single JAXBContext takes tens of seconds since it has to load and process thousands of classes. (Our XSDs are fairly large and complicated.) All JAXBContext instances have different contextpaths - we cannot reduce the number further.
The static helper methods in the JAXB class (JAXB. marshal and JAXB. unmarshall) should be avoided if you need to invoke them repeatedly. Instead, create a JAXBContext instance once and work with the Marshaller and Unmarshaller interfaces.
The JAXBContext. newInstance() method accepts jaxb. index files in the same way that it accepts the ObjectFactory class. Using a jaxb. index file requires you to evaluate all the instances in the trace file that indicate a package does not contain an ObjectFactory class, and create the appropriate jaxb.
JAXBContext is thread safe and should only be created once and reused to avoid the cost of initializing the metadata multiple times. Marshaller and Unmarshaller are not thread safe, but are lightweight to create and could be created per operation.
The JAXBContext class provides the client's entry point to the JAXB API. It provides an abstraction for managing the XML/Java binding information necessary to implement the JAXB binding framework operations: unmarshal, marshal and validate.
The JAXB reference implementation has a sort-of-undocumented system property for exactly this reason:
-Dcom.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.fastBoot=true
or for old versions prior to the package refactoring:
-Dcom.sun.xml.bind.v2.runtime.JAXBContextImpl.fastBoot=true
This instructs JAXB to skip the expensive process of pre-caching the various reflection muscles it needs to do the job. Instead, it will do all the reflection when the context gets used. This makes for a slower runtime, but considerably faster initialization, especially for large numbers of classes.
However, one part of the speed problem is unavoidable, and that's the fact that JAXB has to load every single one of your classes, and classloading is slow. This is apparent if you create a 2nd context immediately after the first, with the same configuration - you'll see it's much, much faster, having already loaded the classes.
Also, you say that you have multiple JAXBContext instances because you have multiple contextpaths. Did you realise that you can put multiple context paths into a single context? You just need to pass them all as a semicolon-delimited string when you initialize the context, e.g.
JaxbContext.newInstance("a.b.c:x.y.z");
will load the contexts a.b.c
and x.y.z
. It likely won't make any difference to performance, though.
In general, you should not have to create many instances of JAXBContext, as they are thread-safe after they have been configured. In most cases just a single context is fine.
So is there specific reason why many instances are created? Perhaps there was assumption they are not thread-safe? (which is understandable given this is not clearly documented -- but it is a very common pattern, need syncing during configuration, but not during usage as long as config is not changed).
Other than this, if this is still a problem, profiling bottlenecks & filing an issue at jaxb.dev.java.net (pointing hot spots from profile) would help in getting things improved. JAXB team is very good, responsive, and if you can show where problems are they usually come up with good solutions.
JAXBContext is indeed thread-safe, so wrapping it with a singleton is advised. I wrote a simple singleton containing a class->context map that seems to do the job. You may also want to create a pool of [un]marshaller objects if you're application uses many threads, as these objects are not thread-safe and you may see some initialization penalties with these as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With