views:

1493

answers:

4

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.

+1  A: 

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.

StaxMan
See the clarification in the question: each instance has different contextpaths, so we cannot reduce the number of instances. The problem is that the initialization of each of those single instances takes tens of seconds.
hstoerr
Ok. Still curious whether it'd be possible to create a dummy "root class" that would statically refer to dependant classes, to allow constructing just one super-context. But there may be other reasons not to do it.What I would suggest if you do have time would really be to do simple profiling, and see where time is spent. As long as any one of contexts is slow to create, running with regular JVM and with -Xhprof, you should see some culprits in stack trace.That could either hint at a workaround, or point JAXB team to improvement(s).
StaxMan
+1  A: 

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.

chetan
See my clarification - this does not help.
hstoerr
If it's taking this long to initialize a single Context, then there may not be much you can do short of profiling the JAXB code itself, as StaxMan suggested. Assuming it's not a long running application where initialization time could be somewhat ignored, you might want to look at other ORMs, though I'm not sure any would be much better in this regard.
chetan
A: 

In our case updating the JAXB libraries was a good idea. Incidentially, using the server VM instead of the client VM even in the development environment was a good idea here, even though it normally slows down server startup: since the JAXB initialization takes so much time the better compilation of the server VM helps.

hstoerr
+2  A: 

The JAXB reference implementation has a sort-of-undocumented system property for exactly this reason:

-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.

skaffman
Just for clarification, you need to use a colon to separate packagenames, not a semi-colon. At least with the Sun JAXB RI.
ThaDon