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

2022-09-02 11:58:44

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

我最初的建议是有一个静态初始值设定项块,该块仅在类加载时初始化这两个实例一次:

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

}

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


答案 1

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

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

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

Marshaller 和 Unmarshaller 的实例不是线程安全的,并且不得在线程之间共享,它们创建起来是轻量级的。


答案 2

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

Marshallers和Unmarshallers很便宜,而且线程不安全。您应该创建一次 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(...);
            ...
    }

}

使用相同的封送处理程序封送所有内容(在创建上下文时添加所有类)。


推荐