139 votes

JAXB créant le contexte et le coût marshallers

La question est un peu théorique, quel est le coût de la création de JAXB contexte, marshaller et unmarshaller?

J'ai trouvé que mon code pourrait bénéficier de maintien de la même JAXB contexte et peut-être le même marshaller pour toutes les opérations de regroupement plutôt que de créer un contexte et marshaller sur chaque regroupement.

Alors, quel est le coût de la création d'JAXB contexte et marshaller/unmarshaller? Est-il possible de créer un contexte+marshaller pour chaque opération de regroupement ou c'est mieux de l'éviter?

285voto

Blaise Doughan Points 75613

Note: je suis le EclipseLink JAXB (MOXy) plomb et un membre de la JAXB 2 (JSR-222) du groupe d'experts.

JAXBContext est thread-safe et ne doit être créé une fois et réutilisés pour éviter le coût de l'initialisation de la métadonnées plusieurs fois. Marshaller et Unmarshaller ne sont pas thread-safe, mais sont légers pour créer et pourrait être créé par l'opération.

17voto

JB Nizet Points 250258

C'est dommage que ce n'est pas précisément décrite dans la javadoc. Ce que je peux dire c'est que le Printemps utilise un mondial JAXBContext, partagé entre les threads, alors qu'il crée un nouveau marshaller pour chaque opération de triage, avec un commentaire javadoc dans le code en disant que JAXB marshallers ne sont pas nécessairement thread-safe.

La même chose est dit sur cette page: http://jaxb.java.net/guide/Performance_and_thread_safety.html.

Je suppose que la création d'un JAXBContext est une opération coûteuse, parce qu'elle implique la numérisation de classes et de packages pour les annotations. Mais la mesure, il est le meilleur moyen de savoir.

3voto

user2773303 Points 31

J'ai résolu ce problème en utilisant JAXBContext et les threads locaux un / marschallers (et donc théoriquement, il y aurait autant d'instances un / marshaller qu'il y a de threads qui y ont accédé) avec synchronisation uniquement lors de l'initialisation de un / marshaller .

 private final ThreadLocal<Unmarshaller> unmarshallerThreadLocal = new ThreadLocal<Unmarshaller>() {
    protected synchronized Unmarshaller initialValue() {
        try {
            return jaxbContext.createUnmarshaller();
        } catch (JAXBException e) {
            throw new IllegalStateException("Unable to create unmarshaller");
        }
    }
};
private final ThreadLocal<Marshaller> marshallerThreadLocal = new ThreadLocal<Marshaller>() {
    protected synchronized Marshaller initialValue() {
        try {
            return jaxbContext.createMarshaller();
        } catch (JAXBException e) {
            throw new IllegalStateException("Unable to create marshaller");
        }
    }
};

private final JAXBContext jaxbContext;

private MyClassConstructor(){
    try {
        jaxbContext = JAXBContext.newInstance(Entity.class);
    } catch (JAXBException e) {
        throw new IllegalStateException("Unable to initialize");
    }
}
 

2voto

tbarderas Points 28

Encore mieux!! Basé sur la bonne solution dans le post ci-dessus, de créer le contexte juste une fois dans le constructeur, et le sauver au lieu de la classe.

Remplacez la ligne:

  private Class clazz;

avec celui-ci:

  private JAXBContext jc;

Et le principal constructeur avec celui-ci:

  private Jaxb(Class clazz)
  {
     this.jc = JAXBContext.newInstance(clazz);
  }

ainsi, dans le getMarshaller/getUnmarshaller vous pouvez supprimer cette ligne:

  JAXBContext jc = JAXBContext.newInstance(clazz);

Cette amélioration permet, dans mon cas, que les délais de traitement des gouttes de 60~70ms à seulement 5~10ms

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X