¿Debo declarar el ObjectMapper de Jackson como un campo estático?

Resuelto Cheok Yan Cheng asked hace 14 años • 6 respuestas

ObjectMapperLa clase de la biblioteca Jackson parece ser segura para subprocesos .

¿Significa esto que debería declarar mi ObjectMappercampo estático como este?

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

en lugar de como un campo a nivel de instancia como este?

class Me {
    private final ObjectMapper mapper = new ObjectMapper();
}
Cheok Yan Cheng avatar Oct 11 '10 23:10 Cheok Yan Cheng
Aceptado

Sí, eso es seguro y recomendado.

La única advertencia de la página a la que hizo referencia es que no puede modificar la configuración del asignador una vez que se comparte; pero no estás cambiando la configuración, así que está bien. Si necesitara cambiar la configuración, lo haría desde el bloque estático y también estaría bien.

EDITAR : (2013/10)

Con 2.0 y superiores, lo anterior se puede ampliar señalando que hay una forma aún mejor: uso ObjectWritery ObjectReaderobjetos, que se pueden construir con ObjectMapper. Son completamente inmutables y seguros para subprocesos, lo que significa que ni siquiera es teóricamente posible causar problemas de seguridad de subprocesos (lo que puede ocurrir ObjectMappersi el código intenta reconfigurar la instancia).

StaxMan avatar Oct 11 '2010 20:10 StaxMan

Aunque ObjectMapper es seguro para subprocesos, desaconsejaría declararlo como una variable estática, especialmente en aplicaciones multiproceso. Ni siquiera porque sea una mala práctica, sino porque corres un gran riesgo de llegar a un punto muerto. Lo digo por experiencia propia. Creé una aplicación con 4 subprocesos idénticos que obtenían y procesaban datos JSON de servicios web. Mi aplicación se detenía con frecuencia con el siguiente comando, según el volcado del hilo:

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

Además de eso, el rendimiento no fue bueno. Cuando reemplacé la variable estática con la variable basada en instancia, el estancamiento desapareció y el rendimiento se cuadruplicó. Es decir, se procesaron 2,4 millones de documentos JSON en 40 min.56 s, en lugar de las 2,5 horas anteriores.

Gary Greenberg avatar Mar 22 '2016 18:03 Gary Greenberg

Un truco que aprendí de este PR si no desea definirlo como una variable final estática pero desea ahorrar un poco de gastos generales y garantizar la seguridad de los subprocesos.

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();
}

crédito al autor.

Lin_n avatar Oct 01 '2018 05:10 Lin_n

Aunque es seguro declarar un ObjectMapper estático en términos de seguridad de subprocesos, debe tener en cuenta que construir variables de objetos estáticas en Java se considera una mala práctica. Para obtener más detalles, consulte ¿Por qué las variables estáticas se consideran malas? (y si quieres, mi respuesta )

En resumen, se debe evitar la estática porque dificulta la escritura de pruebas unitarias concisas. Por ejemplo, con un ObjectMapper final estático, no puede cambiar la serialización JSON por código ficticio o una operación no operativa.

Además, un final estático impide reconfigurar ObjectMapper en tiempo de ejecución. Puede que no imagines una razón para esto ahora, pero si te encierras en un patrón final estático, nada menos que derribar el cargador de clases te permitirá reinicializarlo.

En el caso de ObjectMapper está bien, pero en general es una mala práctica y no hay ninguna ventaja sobre el uso de un patrón singleton o inversión de control para gestionar objetos de larga duración.

JBCP avatar Apr 24 '2013 16:04 JBCP