web-dev-qa-db-ja.com

JAXBContextの初期化の高速化?

多数(> 1000)のクラスでjavax.xml.bind.JAXBContextsの初期化を高速化する方法はありますか? XMLの重いアプリケーションでは、起動時間は約10分で、主にJAXBContextの初期化時間で構成されます。 :-(

XSDからのコード生成には、JDK1.5でのSunのJAXB実装とorg.jvnet.jaxb2.maven2.maven-jaxb2-pluginを使用しています。

明確化:問題は、同じコンテキストパスを持つJAXBContextのインスタンスが多数あることではありませんが、問題は、1つのJAXBContextの初期化に数千のクラスをロードして処理する必要があるため、数十秒かかることです。 (私たちのXSDはかなり大きくて複雑です。)すべてのJAXBContextインスタンスは異なるコンテキストパスを持っています-これ以上数を減らすことはできません。

27

JAXBリファレンス実装には、まさにこの理由から、文書化されていない種類のシステムプロパティがあります。

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

または、パッケージのリファクタリング前の古いバージョンの場合:

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

これにより、JAXBは、ジョブを実行するために必要なさまざまな反射マッスルを事前にキャッシュするという高価なプロセスをスキップするように指示されます。代わりに、コンテキストが使用されるときにすべてのリフレクションを実行します。これにより、ランタイムは遅くなりますが、特に多数のクラスの場合、初期化はかなり速くなります。

ただし、速度の問題の一部は避けられません。それは、JAXBがクラスのすべてをロードする必要があり、クラスのロードが遅いという事実です。これは、最初のコンテキストの直後に同じ構成で2番目のコンテキストを作成した場合に明らかです。すでにクラスをロードしているので、はるかに高速であることがわかります。

また、複数のコンテキストパスがあるため、複数のJAXBContextインスタンスがあると言います。複数のコンテキストパスを1つのコンテキストに入れることができることに気づきましたか?コンテキストを初期化するときに、それらすべてをセミコロンで区切られた文字列として渡す必要があります。

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

コンテキストをロードしますa.b.cおよびx.y.z。ただし、パフォーマンスに影響はない可能性があります。

37
skaffman

一般に、JAXBContextのインスタンスは構成後にスレッドセーフであるため、多くのインスタンスを作成する必要はありません。ほとんどの場合、単一のコンテキストで十分です。

では、多くのインスタンスが作成される特定の理由はありますか?おそらく、それらはスレッドセーフではないという仮定がありましたか? (これは明確に文書化されていないことを考えると理解できますが、これは非常に一般的なパターンであり、構成中に同期する必要がありますが、構成が変更されない限り、使用中に同期する必要はありません)。

これ以外に、これがまだ問題である場合は、ボトルネックのプロファイリングとjaxb.dev.Java.netでの問題のファイリング(プロファイルからホットスポットを指定)が、状況を改善するのに役立ちます。 JAXBチームは非常に優れており、応答性が高く、問題がどこにあるかを示すことができれば、通常は優れた解決策を考え出します。

6
StaxMan

JAXBContextは確かにスレッドセーフであるため、シングルトンでラップすることをお勧めします。私はその仕事をしているように見えるクラス->コンテキストマップを含む単純なシングルトンを書きました。アプリケーションが多くのスレッドを使用している場合は、[un] marshallerオブジェクトのプールを作成することもできます。これらのオブジェクトはスレッドセーフではなく、これらにも初期化のペナルティが発生する可能性があるためです。

3
chetan

私たちの場合、JAXBライブラリを更新することは良い考えでした。ちなみに、クライアントの代わりにサーバーVMを使用するVM開発環境でも、通常はサーバーの起動が遅くなりますが、ここでは良い考えです。 JAXBの初期化には非常に時間がかかるため、サーバーのコンパイルを改善するVMが役立ちます。

1