Should I declare Jackson's ObjectMapper as a static field?

Posted by azhan on Sat, 07 Mar 2020 13:03:35 +0100

ObjectMapper class of Jackson Library Seems thread safe .

Does this mean that I should declare my ObjectMapper as a static field like this?

class Me {
    private static final ObjectMapper mapper = new ObjectMapper();

Instead of instance level fields like this?

class Me {
    private final ObjectMapper mapper = new ObjectMapper();

#1 building

Although it is safe to declare static ObjectMapper in terms of thread safety, you should realize that it is not a good practice to construct static Object variables in Java. For more details, see Why static variables are considered evil? (if you like, My answer )

In short, static methods should be avoided because they make it difficult to write concise unit tests. For example, for static final ObjectMapper, you cannot replace JSON serialization with virtual code or no operation.

In addition, static final prevents you from reconfiguring ObjectMapper at run time. You may not have thought of the reason for this now, but if you lock yourself in static final mode, you can reinitialize it simply by removing the class loader.

In the case of ObjectMapper, it's good, but overall, it's a bad practice, and there's no advantage in using singleton patterns or inversion of control to manage your long-term objects.

#2 building

Although ObjectMapper is thread safe, I strongly recommend not declaring it as a static variable, especially in multithreaded applications. Not even because it's a bad practice, but because you're facing a serious deadlock risk. I speak on the basis of my own experience. I created an application with four identical threads that are fetching and processing JSON data from the Web service. According to thread dump, my application often stops on the following command:

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

In addition, the performance is poor. When I replace static variables with instance based variables, stagnation disappears and performance triples. That is, 2.4 million JSON documents were processed in 40 minutes and 56 seconds, instead of the previous 2.5 hours.

#3 building

Yes, it's safe. I suggest you do.

The only warning about the page you reference is that once the sharer is shared, it cannot be modified. But you don't change the configuration, so you can. If you do need to change the configuration, you can do this from a static block, or you can.

Editor: (October 2013)

In 2.0 and later, you can enhance this by noticing that there is a better way to do it: with ObjectWriter and ObjectReader objects, they can be constructed by ObjectMapper. They are completely immutable and thread safe, which means that in theory it is not even possible to cause thread safety problems (which may occur in ObjectMapper if the code attempts to reconfigure the instance).

#4 building


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.ObjectMapper.convertValue(Object, TypeReference)

The 'hashMapSuperInterfaceChain' method in the com.fasterxml.jackson.databind.type.TypeFactory class is synchronized. See the same competition under high load.

Another reason to avoid static ObjectMapper

#5 building

If you don't want to define it as a static final variable, but want to save some overhead and ensure thread safety, you can PR medium Learn a technique.

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

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

Thanks to the author.

Topics: JSON Java