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

我在基于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(...); ... } } 

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

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

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

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

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

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

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

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

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

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

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

例如JAXB.unmarshal(inputStream / inputFile,outputClassExpected)或JAXB.marshal(jaxbObject,xmlOutputFile / xmlOutputStream)

您应该为每个bean类创建单个JAXBContext对象。 看到这个