Frage

Die ObjectMapper Klasse Jackson Bibliothek scheint Thread-sicher zu sein.

Heißt das, dass ich meine ObjectMapper als statisches Feld wie diese

erklären sollte
class Me {
    private static final ObjectMapper mapper = new ObjectMapper();
}

statt als Instanz-Level-Bereich wie das?

class Me {
    private final ObjectMapper mapper = new ObjectMapper();
}
War es hilfreich?

Lösung

Ja, das ist sicher und empfohlen.

Die einzige Einschränkung von der Seite, die Sie genannt ist, dass Sie nicht Konfiguration des Mapper werden modifizieren können, wenn es geteilt wird; aber sie ändern sich nicht Konfiguration, so dass in Ordnung ist. Wenn Sie ändern müssen Konfiguration haben, würden Sie, dass aus dem statischen Block tun und es wäre in Ordnung als gut.

Bearbeiten : (2013/10)

Mit 2.0 und höher kann oben erweitert werden, mit der Feststellung, dass es eine noch bessere Möglichkeit: Verwendung ObjectWriter und ObjectReader Objekte, die von ObjectMapper konstruiert werden können. Sie sind voll unveränderlich, Thread-sicher, was bedeutet, dass es nicht einmal theoretisch möglich ist, Thread-Sicherheit Probleme zu verursachen (die mit ObjectMapper wenn Code versucht neu konfigurieren Instanz auftreten können).

Andere Tipps

Obwohl ObjectMapper Thread-sicher ist, würde ich stark von entmutigt es als eine statische Variable deklariert, vor allem in Multi-Thread-Anwendung. Nicht einmal, weil es eine schlechte Praxis, sondern weil Sie eine schwere Gefahr von Deadlocks ausgeführt wird. Ich sage es aus meiner eigenen Erfahrung. Ich habe eine Anwendung mit 4 identischen Threads, die JSON-Daten von Web-Service waren immer und Verarbeitung. Mein Antrag wurde auf dem folgenden Befehl häufig Abwürgen nach dem Thread-Dump:

Map aPage = mapper.readValue(reader, Map.class);

Daneben war die Leistung nicht gut. Wenn ich statische Variable mit der Instanz basierend Variable ersetzt, Abwürgen verschwunden und Leistung vervierfacht. D. h 2,4 Millionen JSON Dokumente wurden in 40min.56sec verarbeitet., Anstelle von 2,5 Stunden vorher.

Auch wenn es sicher ist, eine statische ObjectMapper in Bezug auf der Thread-Sicherheit zu erklären, sollten Sie sich bewusst sein, dass in Java statische Objektvariablen konstruiert schlechte Praxis betrachtet wird. Weitere Einzelheiten finden Sie unter Warum statische Variablen Übel betrachtet (und wenn Sie möchten, my Antwort )

Kurz gesagt, sollte Statik, weil die es schwierig machen, zu schreiben kurzen Unit-Tests vermieden werden. Zum Beispiel mit einem statischen endgültigen ObjectMapper, kann man nicht tauschen aus der JSON-Serialisierung für Dummy-Code oder einen no-op.

Darüber hinaus eine statische endgültige verhindert, dass Sie jemals ObjectMapper zur Laufzeit neu zu konfigurieren. Man könnte sich vorstellen, einen Grund, nicht jetzt das, aber wenn Sie sich in ein statisches Endmuster sperren, nichts Geringeres als Abreißen des Classloader nach unten lassen Sie es neu initialisieren.

Im Fall von ObjectMapper seinem feinen, aber im Allgemeinen ist es eine schlechte Praxis und es gibt keinen Vorteil gegenüber der Verwendung eines Singletonmuster oder Inversion of Control Ihre langlebigen Objekte zu verwalten.

Ein Trick, den ich daraus gelernt PR wenn Sie nicht möchten, es als eine statische endgültige Variable zu definieren, aber ein wenig Overhead und Garantiefaden sicher speichern möchten.

private static final ThreadLocal<ObjectMapper> om = new ThreadLocal<ObjectMapper>() {
    @Override
    protected ObjectMapper initialValue() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        return objectMapper;
    }
};

public static ObjectMapper getObjectMapper() {
    return om.get();
}

Kredit an den Autor.

com.fasterxml.jackson.databind.type.TypeFactory._hashMapSuperInterfaceChain (HierarchicType)

com.fasterxml.jackson.databind.type.TypeFactory._findSuperInterfaceChain(Type, Class)
  com.fasterxml.jackson.databind.type.TypeFactory._findSuperTypeChain(Class, Class)
     com.fasterxml.jackson.databind.type.TypeFactory.findTypeParameters(Class, Class, TypeBindings)
        com.fasterxml.jackson.databind.type.TypeFactory.findTypeParameters(JavaType, Class)
           com.fasterxml.jackson.databind.type.TypeFactory._fromParamType(ParameterizedType, TypeBindings)
              com.fasterxml.jackson.databind.type.TypeFactory._constructType(Type, TypeBindings)
                 com.fasterxml.jackson.databind.type.TypeFactory.constructType(TypeReference)
                    com.fasterxml.jackson.databind.ObjectMapper.convertValue(Object, TypeReference)

Die Methode _hashMapSuperInterfaceChain in der Klasse com.fasterxml.jackson.databind.type.TypeFactory ist synchronisiert. Bin Anstoß auf derselben bei hohen Lasten zu sehen.

Auch ein weiterer Grund, eine statische ObjectMapper

zu vermeiden
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top