Devo declarar o ObjectMapper de Jackson como um campo estático?

A class ObjectMapper da biblioteca de Jackson parece ser thread-safe .

Isso significa que devo declarar meu ObjectMapper como um campo estático como este

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

em vez de um campo de instância como esse?

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

Sim, isso é seguro e recomendado.

A única ressalva da página que você mencionou é que você não pode modificar a configuração do mapeador quando ele é compartilhado; mas você não está mudando a configuração, então está tudo bem. Se você precisasse mudar a configuração, você faria isso a partir do bloco estático e também ficaria bem.

EDIT : (2013/10)

Com o 2.0 e acima, o acima pode ser aumentado observando que existe uma maneira ainda melhor: use objects ObjectWriter e ObjectReader , que podem ser construídos pelo ObjectMapper . Eles são totalmente imutáveis, thread-safe, o que significa que não é teoricamente possível causar problemas de segurança de encadeamento (o que pode ocorrer com o ObjectMapper se o código tentar reconfigurar a instância).

Embora o ObjectMapper seja thread-safe, eu seria altamente desencorajador de declará-lo como uma variável estática, especialmente no aplicativo multithread. Nem mesmo porque é uma prática ruim, mas porque você está correndo um grande risco de deadlocking. Estou contando a partir da minha própria experiência. Eu criei um aplicativo com 4 threads idênticos que estavam obtendo e processando dados JSON de serviços da web. Meu aplicativo estava travando com frequência no seguinte comando, de acordo com o dump de thread:

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

Além disso, o desempenho não era bom. Quando substituí a variável estática pela variável baseada em instância, o stalling desapareceu e o desempenho quadruplicou. Ou seja, 2,4 milhões de documentos JSON foram processados ​​em 40min.56s, em vez de 2,5 horas antes.

Embora seja seguro declarar um ObjectMapper estático em termos de segurança de encadeamento, você deve estar ciente de que a construção de variables ​​de object estáticas em Java é considerada uma prática ruim. Para mais detalhes, veja Por que as variables ​​estáticas são consideradas más? (e se você quiser, minha resposta )

Em suma, a estática deve ser evitada porque dificulta a escrita de testes unitários concisos. Por exemplo, com um ObjectMapper final estático, você não pode trocar a serialização do JSON por código fictício ou um não-op.

Além disso, um final estático impede que você reconfigure o ObjectMapper no tempo de execução. Você pode não imaginar uma razão para isso agora, mas se você se prender a um padrão final estático, nada menos do que derrubar o carregador de class permitirá reinicializá-lo.

No caso do ObjectMapper é bom, mas em geral é uma má prática e não há vantagem sobre o uso de um padrão singleton ou inversão de controle para gerenciar seus objects de vida longa.

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) 

O método _hashMapSuperInterfaceChain na class com.fasterxml.jackson.databind.type.TypeFactory é sincronizado. Estou vendo contenção no mesmo em altas cargas.

Pode ser outro motivo para evitar um ObjectMapper estático