2009-04-27 15 views
24

Gibt es eine Möglichkeit, die Initialisierung von javax.xml.bind.JAXBContexts mit einer großen (> 1000) Anzahl von Klassen zu beschleunigen? In unserer XML-Heavy-Applikation beträgt die Startzeit ca. 10 Minuten und besteht hauptsächlich aus der Initialisierungszeit der JAXBContexts. :-(JAXBContext Initialisierung Beschleunigung?

Wir Sun JAXB Umsetzung im JDK verwenden 1.5 und die org.jvnet.jaxb2.maven2.maven-jaxb2-Plugin für die Code-Generierung aus XSDs

Klarstellung:. Das Problem ist nicht, dass Wir haben viele Instanzen eines JAXBContext mit den gleichen Kontextpfaden, aber das Problem ist, dass die Initialisierung eines einzelnen JAXBContext einige Sekunden dauert, da es Tausende von Klassen laden und verarbeiten muss. (Unsere XSDs sind ziemlich groß und kompliziert.) Alle JAXBContext Instanzen haben unterschiedliche Kontextpfade - wir können die Zahl nicht weiter reduzieren

Antwort

32

Die JAXB Referenz-Implementierung hat eine Art-of-undokumentierte Systemeigenschaft für genau diesen Grund:

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

oder für alte Versionen vor dem Paket Refactoring:

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

Dies weist JAXB zu Überspringen Sie den teuren Prozess der Vorabspeicherung der verschiedenen Reflexionsmuskeln, die für diese Aufgabe erforderlich sind. Stattdessen wird es die gesamte Reflexion tun, wenn der Kontext verwendet wird. Dies führt zu einer langsameren Laufzeit, aber zu einer wesentlich schnelleren Initialisierung, insbesondere bei einer großen Anzahl von Klassen.

Allerdings ist ein Teil des Geschwindigkeitsproblems unvermeidlich, und das ist die Tatsache, dass JAXB jede einzelne Ihrer Klassen laden muss und das Classloading langsam ist. Dies ist offensichtlich, wenn Sie einen zweiten Kontext direkt nach dem ersten mit der gleichen Konfiguration erstellen - Sie werden sehen, dass es viel, viel schneller ist, die Klassen bereits geladen zu haben.

Sie sagen auch, dass Sie mehrere JAXBCOntext-Instanzen haben, weil Sie mehrere Kontextpfade haben.Ist Ihnen aufgefallen, dass Sie mehrere Kontextpfade in einen einzigen Kontext einfügen können? Sie müssen sie nur alle als durch Semikolons getrennte Zeichenfolge übergeben, wenn Sie den Kontext initialisieren, z.

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

werden die Kontexte laden a.b.c und x.y.z. Es wird jedoch wahrscheinlich keinen Unterschied für die Leistung machen.

+5

Nur zur Klarstellung, müssen Sie einen Doppelpunkt verwenden, um Paketnamen, kein Semikolon zu trennen. Zumindest mit der Sun JAXB RI. – ThaDon

6

Im Allgemeinen sollten Sie nicht viele Instanzen von JAXBContext erstellen müssen, da sie threadsicher sind wurden konfiguriert. In den meisten Fällen ist nur ein einziger Kontext in Ordnung.

Gibt es einen bestimmten Grund, warum viele Instanzen erstellt werden? Vielleicht gab es die Vermutung, dass sie nicht threadsicher sind? (Das ist verständlich, da dies nicht eindeutig dokumentiert ist - aber es ist ein sehr häufiges Muster, das während der Konfiguration synchronisiert werden muss, aber nicht während der Verwendung, solange die Konfiguration nicht geändert wird).

Abgesehen davon, wenn das immer noch ein Problem ist, würde Profiling Engpässe & ein Problem bei jaxb.dev.java.net (Hot Spots aus Profil anzeigen) helfen, um Dinge zu verbessern. JAXB Team ist sehr gut, reaktionsschnell, und wenn Sie zeigen können, wo Probleme sind, haben sie in der Regel gute Lösungen.

+0

Siehe die Erläuterung in der Frage: jede Instanz hat andere Kontextpfade, so dass wir die Anzahl der Instanzen nicht reduzieren können. Das Problem besteht darin, dass die Initialisierung jeder dieser einzelnen Instanzen mehrere Sekunden dauert. –

+0

Ok. Immer noch neugierig, ob es möglich wäre, eine Dummy-Wurzelklasse zu erstellen, die sich statisch auf abhängige Klassen beziehen würde, um nur einen Superkontext zu konstruieren. Aber es könnte andere Gründe geben, es nicht zu tun. Was ich vorschlagen würde, wenn Sie Zeit haben, wäre wirklich, einfache Profilerstellung zu tun und zu sehen, wo Zeit verbracht wird. Solange einer der Kontexte langsam erstellt wird und mit regulärer JVM und -Xhprof ausgeführt wird, sollten Sie einige Fehler in der Stack-Ablaufverfolgung sehen. Das könnte entweder einen Workaround anzeigen oder das JAXB-Team auf Verbesserungen hinweisen. – StaxMan

+0

@hstoerr Da der Initialisierungsprozess ~ 10 Sekunden dauert, wäre es nicht am praktischsten, den Initialisierungsprozess beim Start der Anwendung parallel durchzuführen? – Nielsvh

3

JAXBContext ist in der Tat threadsicher, daher ist es ratsam, es mit einem Singleton zu umhüllen. Ich schrieb ein einfaches Singleton, das eine Klasse-> Kontextkarte enthielt, die die Aufgabe zu erledigen schien. Vielleicht möchten Sie auch einen Pool von [un] Marshaller-Objekten erstellen, wenn Ihre Anwendung viele Threads verwendet, da diese Objekte nicht threadsicher sind und Sie möglicherweise auch einige Fehler bei der Initialisierung sehen.

+0

Siehe meine Klarstellung - das hilft nicht. –

+0

Wenn es so lange dauert, einen einzelnen Kontext zu initialisieren, dann kann es nicht viel geben, was Sie tun können, um den JAXB-Code selbst zu profilieren, wie StaxMan vorgeschlagen hat. Angenommen, es ist keine lange laufende Anwendung, bei der die Initialisierungszeit etwas ignoriert werden könnte, sollten Sie sich andere ORMs ansehen, obwohl ich mir nicht sicher bin, ob es in dieser Hinsicht viel besser wäre. – chetan

1

In unserem Fall war die Aktualisierung der JAXB-Bibliotheken eine gute Idee. Die Verwendung der Server-VM anstelle der Client-VM selbst in der Entwicklungsumgebung war hier eine gute Idee, obwohl sie normalerweise den Server-Start verlangsamt: Da die JAXB-Initialisierung so viel Zeit in Anspruch nimmt, hilft die bessere Kompilierung der Server-VM.