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

rya*_*yan 19 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(...);
            ...
    }

}
Run Code Online (Sandbox Code Playgroud)

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

bdo*_*han 28

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

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

为避免创建JAXBContext实例所涉及的开销,建议JAXB应用程序重用JAXBContext实例.抽象类JAXBContext的实现需要是线程安全的,因此,应用程序中的多个线程可以共享同一个JAXBContext实例.

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


coc*_*llo 9

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

}
Run Code Online (Sandbox Code Playgroud)

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

  • 只是评论:你不应该重复使用marshallers/unmarshallers,他们不是线程安全的.只需每次创建它们,速度非常快 (2认同)
  • 我认为这里建议的解决方案是现场解决方案,非常有用,但我不相信代码示例说明了每次需要Marshaller时你不应该调用JAXBContext.newInstance()的文本中的观点. .doSomething()中的行不应该是`requestMarshaller = jaxbContext.createMarshaller();`? (2认同)