如何提高使用JAXBContext.newInstance操作的应用程序的性能?

时间:2011-05-18 11:31:30

标签: java xml jaxb

我在基于JBoss的Web应用程序中使用JAXBContext.newInstance操作。据我所知,这项行动是非常重量级的。我只需要Marshaller类的两个唯一实例。

我的初步建议是使用静态初始化程序块,只在类加载时初始化这两个实例:

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(...);
            ...
    }

}

如果这是一个合理的解决方案,那么我想我已经回答了我自己的问题,但我想知道这是否是正确的方法呢?

5 个答案:

答案 0 :(得分:26)

JAXB实现(MetroEclipseLink MOXyApache JaxMe等)通常在JAXBContext.newInstance调用期间初始化其元数据。所有OXM工具都需要在某个时刻初始化映射元数据,并尝试最小化此操作的成本。由于不可能以零成本完成,因此最好只进行一次。 JAXBContext的实例是线程安全的,所以是的,你只需要创建一次。

从JAXB 2.2规范,第4.2节JAXB上下文:

  

避免涉及的开销   创建一个JAXBContext实例,一个   鼓励JAXB应用程序   重用JAXBContext实例。一个   抽象类的实现   需要JAXBContext   线程安全,因此,多个线程   应用程序可以共享相同的内容   JAXBContext实例。

Marshaller和Unmarshaller的实例不是线程安全的,不能在线程之间共享,它们是轻量级的。

答案 1 :(得分:8)

JAXBContext应该始终是静态的,它是线程安全的。

Marshallers和Unmarshallers很便宜而且不是线程安全的。您应该创建一次JAXBContext并为每个操作创建marshallers / unmarshallers

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(...);
            ...
    }

}

使用相同的编组器来编组所有内容(在创建上下文时添加所有类)。

答案 2 :(得分:4)

我最近使用JAXBContext.newInstance进行了一些性能测试,结果记录在这里。

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

当一个线程调用时,使用一个包含~195个类的相当大的模式,完成需要大约400ms。当同时被20个线程调用时,它会引起cpu争用,并且需要大约5000ms才能完成。创建marshaller和对象序列化只是一个小对象~14ms。

答案 3 :(得分:0)

可以使用javax.xml.bind.JAXB。它有直接的Marshal和unmarshal方法。因此,您不必担心JAXB的实例创建。

e.g。 JAXB.unmarshal(inputStream / inputFile,outputClassExpected) 或JAXB.marshal(jaxbObject,xmlOutputFile / xmlOutputStream)

答案 4 :(得分:-1)

您应该为每个bean类创建单个JAXBContext对象。见this

相关问题