Date: 4 Dec 2014 15:33:56 CET
Subject: [eclipselink-dev]
Moxy expensive classloader search when using elements with
primitive types
Hi,
this post was originally sent to the users list. There was no
response and it is probably more appropriate for the dev list,
so moving here.
I analyzed a performance problem of an application using Moxy.
It turned out that threads were blocking on the classloader
lock. This was due to JaxbClassLoader frequently calling
loadClass() on its parent loader.
The root cause was a combination of two factors:
- no reuse of the JAXBContext
- use of xsd:int (and other primitive types) as *element*
types
What happens, is that JAXBContext was looking for xsd:int and
that went to the JaxbClassLoader calling loadClass("int").
That type of course isn't known so the parent classloader had
to search through all of its jars to check. In our case the
search was further delegated from a web app classloader to the
system classloader to the bootstrap classloader. The latter
two do not have caches for not found resources, so each time a
new JAXBContext tried to resolve "int", the search was done.
Each of the classloaders involved ends the search with
creating an (expensive) ClassNotFoundException. Since this
takes quite some time, the classloader locks got contented and
threads piled up.
Note that if you use xsd:int as the type of an *attribute*,
this does not happen. Moxy will map that straight to "Integer"
instead of searching for "int". Only when using xsd:int for an
*element* that problem shows up. The problem also does not
happen when using the JAXB reference implementation.
I'm not saying, that the final result is broken. After the
CNFE from the parent classloader, Moxy finally maps e.g. an
xsd:int element to the Java primitive int. I'm only saying
that doing a classloader search for a primitive type is
expensive and should not be done.
I know that this wouldn't have hurt so much, if we had reused
the JAXBContext. Nevertheless I think that it would be easy to
improve JaxbClassLoader. As a workaround we can use a mapping
file to map the primitive types to the corresponding object
types during xjc, but that should not be necessary.
I'll attach a simple example project, hopefully attachments
are allowed here. It contains a README and you can simply run
it with "ant" using Moxy 2.5.x. It contains a slightly patched
version of JaxbClassLoader to make the CNFE from the parent
classloader observable by output to STDOUT. It first runs the
example using attributes - no primitives loading - then using
elements showing the primitives loading and CNFE.
I'll also attach a draft patch for improving the
JaxbClassLoader.
Regards,
Rainer