2009-04-27 13 views
24

¿Hay alguna manera de acelerar la inicialización de javax.xml.bind.JAXBContexts con un número grande (> 1000) de clases? En nuestra aplicación pesada XML, el tiempo de inicio es de unos 10 minutos y consiste principalmente en el tiempo de inicialización de JAXBContexts. :-(JAXBContext initialization speedup?

Estamos utilizando la aplicación JAXB de Sun en el JDK 1.5 y el plug-in-jaxb2-org.jvnet.jaxb2.maven2.maven para la generación de código de XSDs

Aclaración:. El problema no es que tenemos muchas instancias de un JAXBContext con los mismos paths contextuales, pero el problema es que la inicialización de un solo JAXBContext lleva decenas de segundos, ya que tiene que cargar y procesar miles de clases. (Nuestros XSD son bastante grandes y complicados). Todos los JAXBContext las instancias tienen diferentes paths contextuales, no podemos reducir el número más.

Respuesta

32

La implementación de referencia JAXB tiene una propiedad del sistema clase-de-indocumentado exactamente por esta razón:

-Dcom.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.fastBoot=true 

o para versiones antiguas antes de la refactorización paquete:

-Dcom.sun.xml.bind.v2.runtime.JAXBContextImpl.fastBoot=true 

Esto indica JAXB a omita el costoso proceso de precaching de los diversos músculos de reflexión que necesita para hacer el trabajo. En cambio, hará toda la reflexión cuando se use el contexto. Esto permite un tiempo de ejecución más lento, pero una inicialización considerablemente más rápida, especialmente para grandes cantidades de clases.

Sin embargo, una parte del problema de velocidad es inevitable, y ese es el hecho de que JAXB tiene que cargar cada una de sus clases, y la carga de clases es lenta. Esto es evidente si crea un segundo contexto inmediatamente después del primero, con la misma configuración: verá que es mucho, mucho más rápido, ya que ha cargado las clases.

Además, dices que tienes varias instancias de JAXBCOntext porque tienes varios paths contextuales.¿Te diste cuenta de que puedes poner múltiples rutas de contexto en un solo contexto? Solo debe pasarlos todos como una cadena delimitada por punto y coma cuando inicialice el contexto, p.

JaxbContext.newInstance("a.b.c:x.y.z"); 

cargará los contextos a.b.c y x.y.z. Sin embargo, probablemente no hará ninguna diferencia en el rendimiento.

+5

Solo para aclararlo, debe usar dos puntos para separar los nombres de los paquetes, no un punto y coma. Al menos con el Sun JAXB RI. – ThaDon

6

En general, no debería tener que crear muchas instancias de JAXBContext, ya que son seguras para hilos después de que han sido configurados En la mayoría de los casos, solo un único contexto está bien.

¿Hay alguna razón específica por la que se crean muchas instancias? ¿Tal vez se asumió que no son seguros para subprocesos? (lo cual es comprensible dado que esto no está claramente documentado, pero es un patrón muy común, necesita sincronización durante la configuración, pero no durante el uso, siempre y cuando la configuración no se modifique).

Aparte de esto, si esto todavía es un problema, perfilar los cuellos de botella & archivar un problema en jaxb.dev.java.net (señalando los puntos calientes del perfil) ayudaría a mejorar las cosas. El equipo de JAXB es muy bueno, receptivo, y si puede mostrar dónde están los problemas, suelen encontrar buenas soluciones.

+0

Consulte la aclaración en la pregunta: cada instancia tiene diferentes paths contextuales, por lo que no podemos reducir el número de instancias. El problema es que la inicialización de cada una de esas instancias individuales lleva decenas de segundos. –

+0

Ok. Todavía tengo curiosidad de si sería posible crear una "clase raíz" ficticia que se refiera estáticamente a las clases dependientes, para permitir construir solo un supercontexto. Pero puede haber otras razones para no hacerlo. Lo que yo sugeriría si tuviera tiempo sería hacer un perfil simple y ver dónde se gasta el tiempo. Mientras uno de los contextos sea lento de crear, se ejecute con JVM normal y con -Xhprof, debería ver algunos culpables en el seguimiento de la pila. Eso podría indicar una solución alternativa o indicar al equipo de JAXB las mejoras. – StaxMan

+0

@hstoerr Debido a que el proceso de inicialización lleva ~ 10 segundos, ¿no sería más práctico realizar el proceso de inicialización en paralelo al inicio de la aplicación? – Nielsvh

3

JAXBContext es realmente seguro para subprocesos, por lo que se recomienda envolverlo con un singleton. Escribí un singleton simple que contiene un mapa de contexto de clase que parece hacer el trabajo. También es posible que desee crear un grupo de objetos [un] marshaller si su aplicación utiliza muchos subprocesos, ya que estos objetos no son seguros para subprocesos y es posible que vea algunas penalizaciones de inicialización con estos.

+0

Ver mi aclaración: esto no ayuda. –

+0

Si lleva tanto tiempo inicializar un único contexto, puede que no haya mucho que pueda hacer para crear un perfil del código JAXB en sí mismo, como lo sugirió StaxMan. Suponiendo que no se trata de una aplicación de larga ejecución en la que el tiempo de inicialización podría ser ignorado, es posible que desee examinar otros ORM, aunque no estoy seguro de que alguno sea mucho mejor en este sentido. – chetan

1

En nuestro caso, la actualización de las bibliotecas JAXB fue una buena idea. Incidentalmente, usar la máquina virtual del servidor en lugar de la máquina virtual del cliente incluso en el entorno de desarrollo fue una buena idea, aunque normalmente ralentiza el inicio del servidor: dado que la inicialización de JAXB toma mucho tiempo, la mejor compilación de la máquina virtual del servidor ayuda.

Cuestiones relacionadas