How To Improve Perforamance of Jaxb

Creating the JAXB unmashaller via :

javax.xml.bind.JAXBContext.newInstance()

is a very slow operation, if you intending to unmashaller a number of xml documents all with the same schema, you can greatly improve performance by caching the unmashaller instance, see below :

import org.xml.sax.InputSource;
 
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
 
public final class JaxBWrapper<T> {
 
    private final Unmarshaller unmarshaller;
    private static final Map<ContextDescriptor, Unmarshaller> cache = new HashMap();
 
    /**
     * Creating the JAXB unmashaller via :
     * <p/>
     * javax.xml.bind.JAXBContext.newInstance() is a very slow operation, you can greating improve your performance if you create a cache of these instances, we do this by wrapping the call to newInstance with the following code
     */
    private static class ContextDescriptor {
 
        private final String jaxbContext;
        private final String schemaLocation;
 
        public boolean equals(Object o) {
            if (o instanceof ContextDescriptor) {
                final ContextDescriptor un = ((ContextDescriptor) o);
                return jaxbContext.equals(un.jaxbContext) && schemaLocation.equals(un.schemaLocation);
            }
            return false;
        }
 
        public int hashCode() {
            return (jaxbContext + schemaLocation).hashCode();
        }
 
        ContextDescriptor(String jaxbContext, String schemaLocation) {
            this.jaxbContext = jaxbContext.trim();
            this.schemaLocation = schemaLocation.trim();
        }
    }
 
    public JaxBWrapper(final String jaxbContext, final String schemaLocation) {
        unmarshaller = getInstance(jaxbContext, schemaLocation);
    }
 
    public JaxBWrapper(final String jaxbContex) {
        this(jaxbContex, "your root xsd file path");
    }
 
    private static Unmarshaller getInstance(final String jaxbContext, final String schemaLocation) {
 
        final ContextDescriptor contextDescriptor = new ContextDescriptor(jaxbContext, schemaLocation);
        final Unmarshaller unmarshaller = cache.get(contextDescriptor);
 
        if (unmarshaller != null)
            return unmarshaller;
 
        final Unmarshaller result = newInstance(jaxbContext, schemaLocation);
        cache.put(contextDescriptor, result);
        return result;
    }
 
    private static Unmarshaller newInstance(final String jaxbContext, final String schemaLocation) {
        try {
            final JAXBContext context = JAXBContext.newInstance(jaxbContext);
            final Unmarshaller result = context.createUnmarshaller();
 
            final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
 
            try {
                URI uri = Thread.currentThread().getContextClassLoader().getResource(schemaLocation).toURI()
                final Schema s = schemaFactory.newSchema(toStreamSources(uri));
                result.setSchema(s);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            return result;
        }
        catch (JAXBException e) {
            throw new RuntimeException("Exception occured creating JAXB unmarshaller for context=" + jaxbContext, e);
        }
 
    }
 
    public T unmarshallXMLString(final String xmlString) throws Exception {
        final StringReader sr = new StringReader(xmlString.trim());
        final InputSource is = new InputSource(sr);
        return (T) unmarshaller.unmarshal(is);
    }
 
    static Source[] toStreamSources(@NotNull final URI stream) {
        return new Source[]{new StreamSource(stream.toString())};
    }
}

If this dose not give you the performance increase that you are looking for, then consider using a SAX parser. If you wish to use a pull parser you could consider using StAX.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License