Sí, eso es seguro y recomendado.
La única advertencia de la página que mencionó es que no puede modificar la configuración del mapeador una vez que se comparte; pero no está cambiando la configuración, así que está bien. Si necesita 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 versiones superiores, se puede aumentar la versión anterior al señalar que hay una forma aún mejor: el uso ObjectWritery los ObjectReaderobjetos, que pueden ser construidos por ObjectMapper. Son completamente inmutables, seguros para subprocesos, lo que significa que ni siquiera es teóricamente posible causar problemas de seguridad de subprocesos (que pueden ocurrir ObjectMappersi el código intenta reconfigurar la instancia).
ObjectMappertodavía es seguro para subprocesos después de queObjectMapper#setDateFormat()se llama. Se sabe queSimpleDateFormatno es seguro para subprocesos , porObjectMapperlo que no lo será a menos que clone, por ejemplo,SerializationConfigantes de cada unowriteValue()(dudo). ¿Podrías desacreditar mi miedo?DateFormatde hecho está clonado debajo del capó. Buena sospecha allí, pero estás cubierto. :)ObjectMapperen absoluto ?! Los métodos se nombranwriter()yreader()(y algunosreaderFor(),writerFor()).mapper.with()llamada (ya que "con" en Jackson implica la construcción de una nueva instancia y una ejecución segura para subprocesos). Pero con respecto a los cambios de configuración: no se realiza ninguna comprobación, por lo que seObjectMapperdebe proteger el acceso a la configuración . En cuanto a "copy ()": sí, eso crea una nueva copia nueva que puede ser completamente (re) configurada, de acuerdo con las mismas reglas: configúrela completamente primero, luego úsela, y eso está bien. Hay un costo no trivial asociado (ya que la copia no puede usar ninguno de los controladores en caché), pero es la forma segura, sí.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 bloqueo. Lo digo desde mi propia experiencia. Creé una aplicación con 4 hilos idénticos que obtenían y procesaban datos JSON de los servicios web. Mi aplicación se detenía con frecuencia en el siguiente comando, de acuerdo con el volcado de subprocesos:
Además de eso, el rendimiento no fue bueno. Cuando reemplacé la variable estática con la variable basada en la instancia, el bloqueo desapareció y el rendimiento se cuadruplicó. Es decir, 2,4 millones de documentos JSON se procesaron en 40min.56seg., En lugar de 2.5 horas antes.
fuente
ObjectMapperinstancia para cada instancia de clase puede evitar bloqueos, pero puede ser muy pesado en GC más adelante (imagine una instancia de ObjectMapper para cada instancia de la clase que cree). Un enfoque de ruta intermedia puede ser, en lugar de mantener solo unaObjectMapperinstancia estática (pública) en la aplicación, puede declarar una instancia estática (privada)ObjectMapperen cada clase . Esto reducirá un bloqueo global (al distribuir la carga a nivel de clase) y tampoco creará ningún objeto nuevo, por lo tanto, también se iluminará el GC.ObjectPooles la mejor manera de avanzar, brindando lo mejorGCy el mejorLockrendimiento. Puede consultar el siguiente enlace para laObjectPoolimplementación de apache-common . commons.apache.org/proper/commons-pool/api-1.6/org/apache/…ObjectMapperalgún lugar, pero solo obtenerObjectReader/ObjectWriterinstancias (a través de métodos auxiliares), retener referencias a aquellos en otros lugares (o llamar dinámicamente). Estos objetos de lector / escritor no solo son una reconfiguración de wrt totalmente segura para subprocesos, sino que también son muy livianos (instancias de mapeador de wrt). Por lo tanto, mantener miles de referencias no agrega mucho uso de memoria.Aunque es seguro declarar un ObjectMapper estático en términos de seguridad de subprocesos, debe tener en cuenta que la construcción de variables Object 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, las estadísticas deben evitarse porque dificultan la redacción de pruebas unitarias concisas. Por ejemplo, con un ObjectMapper final estático, no puede intercambiar la serialización JSON por código ficticio o no operativo.
Además, una final estática le impide volver a configurar ObjectMapper en tiempo de ejecución. Puede que no imagines una razón para eso ahora, pero si te encierras en un patrón final estático, nada menos que derribar el cargador de clases te permitirá reiniciarlo.
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 administrar sus objetos de larga duración.
fuente
readerForywriterForque creaObjectReadereObjectWriterinstancias bajo demanda. ¿Entonces diría que coloque el mapeador con la configuración inicial en algún lugar estático, luego obtenga lectores / escritores con la configuración por caso cuando los necesite?Un truco que aprendí de este PR si no quieres definirlo como una variable final estática pero quieres ahorrar un poco de sobrecarga y garantizar un hilo seguro.
crédito al autor.
fuente
ObjectMapperque se conectará al hilo que puede ser parte de un grupo.com.fasterxml.jackson.databind.type.TypeFactory._hashMapSuperInterfaceChain (HierarchicType)
El método _hashMapSuperInterfaceChain en la clase com.fasterxml.jackson.databind.type.TypeFactory está sincronizado. Estoy viendo contenciones sobre lo mismo en grandes cargas.
Puede ser otra razón para evitar un ObjectMapper estático
fuente
TypeReferencees algo un poco costoso de usar: si es posible, resolverloJavaTypeevitaría una gran cantidad de procesamiento (TypeReferencedesafortunadamente, los s no se pueden almacenar en caché por razones que no voy a investigar aquí), ya que están "totalmente resueltos" (supertipo, tipificación genérica, etc.).