Должен ли я объявлять ObjectMapper Jackson как статическое поле?

Библиотека Jackson ObjectMapper class кажется потокобезопасной.

Означает ли это, что я должен объявить мой ObjectMapper как статическое поле, подобное этому

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

вместо поля типа экземпляра, подобного этому?

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

Ответ 1

Да, это безопасно и рекомендуется.

Единственное предостережение со страницы, о которой вы говорили, заключается в том, что вы не можете изменять конфигурацию картографа после его совместного использования; но вы не меняете конфигурацию, так что это нормально. Если вам нужно было изменить конфигурацию, вы сделали бы это из статического блока, и это тоже было бы хорошо.

EDIT: (2013/10)

С 2.0 и выше выше можно увеличить, отметив, что существует еще лучший способ: использовать объекты ObjectWriter и ObjectReader, которые могут быть построены с помощью ObjectMapper. Они полностью неизменяемы, потокобезопасны, а это означает, что теоретически невозможно вызвать проблемы безопасности потоков (что может произойти с ObjectMapper, если код пытается перенастроить экземпляр).

Ответ 2

Хотя ObjectMapper является потокобезопасным, я бы сильно отказался от объявления его как статической переменной, особенно в многопоточном приложении. Даже не потому, что это плохая практика, а потому, что вы столкнулись с серьезным риском блокировки. Я рассказываю это по собственному опыту. Я создал приложение с 4 идентичными потоками, которые получали и обрабатывали данные JSON из веб-служб. Мое приложение часто останавливалось на следующей команде в соответствии с дампом потока:

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

Кроме того, производительность не была хорошей. Когда я заменил статическую переменную на переменную, основанную на экземпляре, исчезновение сваливания и производительность увеличились в четыре раза. То есть 2.4 миллиона документов JSON обрабатывались за 40 мин .56 сек. Вместо 2,5 часов ранее.

Ответ 3

Хотя безопасно объявлять статический ObjectMapper с точки зрения безопасности потоков, вы должны знать, что построение статических переменных Object в Java считается плохой практикой. Для получения дополнительной информации см. Почему статические переменные считаются злыми? (и если хотите, мой ответ)

Короче говоря, статики следует избегать, потому что затруднять запись сжатых модульных тестов. Например, со статическим окончательным ObjectMapper вы не можете поменять сериализацию JSON на фиктивный код или нет-op.

Кроме того, статический финал не позволяет вам переконфигурировать ObjectMapper во время выполнения. Теперь вы можете не предвидеть причину этого, но если вы закроете себя в статическом окончательном шаблоне, ничего, кроме разрыва загрузчика классов, не позволит вам повторно инициализировать его.

В случае ObjectMapper это нормально, но в целом это плохая практика, и нет преимущества перед использованием шаблона singleton или инверсии управления для управления вашими долговечными объектами.

Ответ 4

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)

Метод _hashMapSuperInterfaceChain в классе com.fasterxml.jackson.databind.type.TypeFactory синхронизирован. Я вижу конкуренцию на том же уровне при высоких нагрузках.

Может быть, еще одна причина избежать статического ObjectMapper