web-dev-qa-db-ja.com

JAXBContext.newInstance操作を使用するアプリケーションのパフォーマンスを向上させるにはどうすればよいですか?

JBossベースのWebアプリケーションでJAXBContext.newInstance操作を使用します。私が理解しているように、この操作は非常に重いものです。マーシャラークラスの2つの一意のインスタンスのみが必要です。

私の最初の提案は、クラスのロード時にこれら2つのインスタンスを1回だけ初期化する静的初期化ブロックを用意することです。

public class MyWebApp {
    private static Marshaller requestMarshaller;
    private static Marshaller responseMarshaller;

    static {
        try {
            // one time instance creation
            requestMarshaller = JAXBContext.newInstance(Request.class).createMarshaller();
            responseMarshaller = JAXBContext.newInstance(Response.class).createMarshaller();
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

    private void doSomething() {
            requestMarshaller.marshall(...);
            responseMarshaller.marshall(...);
            ...
    }

}

これが合理的な解決策である場合、私は自分の質問に答えたと思いますが、これがこれを行う正しい方法であるかどうかを知りたいですか?

19
ryan

JAXB実装( MetroEclipseLink MOXyApache JaxMe など)は通常、JAXBContext.newInstance呼び出し中にメタデータを初期化します。すべてのOXMツールは、ある時点でマッピングメタデータを初期化し、この操作のコストを最小限に抑えるようにする必要があります。ゼロコストでそれを行うことは不可能なので、一度だけ行うのが最善です。 JAXBContextのインスタンスはスレッドセーフであるため、作成する必要があるのは1回だけです。

JAXB 2.2仕様、セクション4.2 JAXBコンテキストから:

JAXBContextインスタンスの作成に伴うオーバーヘッドを回避するために、JAXBアプリケーションはJAXBContextインスタンスを再利用することをお勧めします。抽象クラスJAXBContextの実装はスレッドセーフである必要があるため、アプリケーション内の複数のスレッドが同じJAXBContextインスタンスを共有できます。

MarshallerとUnmarshallerのインスタンスはスレッドセーフではなく、スレッド間で共有してはなりません。作成が軽量です。

27
bdoughan

JAXBContextは常に静的である必要があり、スレッドセーフです。

マーシャラーとアンマーシャラーは安価であり、スレッドセーフではありません。 JAXBContextを一度作成し、すべての操作に対してマーシャラー/アンマーシャラーを作成する必要があります

public class MyWebApp {
    private static JAXBContext jaxbContext;

    static {
        try {
            // one time instance creation
            jaxbContext = JAXBContext.newInstance(Request.class, Response.class);
        } catch (JAXBException e) {
            throw new IllegalStateException(e);
        }
    }

    private void doSomething() {                
            jaxbContext.createMarshaller().marshall(...);
            ...
    }

}

同じマーシャラーを使用してすべてをマーシャリングします(コンテキストを作成するときにすべてのクラスを追加します)。

8
cocorossello

最近、JAXBContext.newInstanceを使用してパフォーマンステストを行いました。結果は、ここに記載されています。

http://app-inf.blogspot.com/2012/10/performance-tuning-logging-right-way.html

〜195のクラスが生成されたかなり大きなスキーマを使用して、1つのスレッドによって呼び出された場合、完了するまでに〜400msかかりました。 20個のスレッドによって同時に呼び出されると、CPUの競合が発生し、完了するまでに最大5000ミリ秒かかりました。マーシャラーの作成と小さなオブジェクトのオブジェクトのシリアル化は、わずか14ミリ秒です。

4
user1738754

Javax.xml.bind.JAXBを使用できます。直接マーシャルとアンマーシャルの方法があります。したがって、JAXBのインスタンス作成について心配する必要はありません。

例えばJAXB.unmarshal(inputStream/inputFile、outputClassExpected)またはJAXB.marshal(jaxbObject、xmlOutputFile/xmlOutputStream)

0
sandeep kale