From 30cc98d1ef31be62daf5a201866dfa3482f4690f Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Thu, 28 Mar 2024 19:43:50 +0100 Subject: [PATCH 1/3] remove synchronized block from BeanDeserializerBase --- .../databind/deser/BeanDeserializerBase.java | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java index 3007714a1d..bb26443a8e 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java @@ -4,6 +4,8 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReentrantLock; import com.fasterxml.jackson.annotation.*; @@ -177,8 +179,14 @@ public abstract class BeanDeserializerBase * Note that this is only needed for polymorphic types, * that is, when the actual type is not statically known. * For other types this remains null. + * The map type changed in 2.18 (from HashMap to ConcurrentHashMap) */ - protected transient HashMap> _subDeserializers; + protected transient ConcurrentHashMap> _subDeserializers; + + /** + * Lock used to prevent multiple creation of _subDeserializers map + */ + private final ReentrantLock _subDeserializersLock = new ReentrantLock(); /** * If one of properties has "unwrapped" value, we need separate @@ -1882,12 +1890,9 @@ protected JsonDeserializer _findSubclassDeserializer(DeserializationCont Object bean, TokenBuffer unknownTokens) throws IOException { - JsonDeserializer subDeser; - // First: maybe we have already created sub-type deserializer? - synchronized (this) { - subDeser = (_subDeserializers == null) ? null : _subDeserializers.get(new ClassKey(bean.getClass())); - } + ClassKey classKey = new ClassKey(bean.getClass()); + JsonDeserializer subDeser = (_subDeserializers == null) ? null : _subDeserializers.get(classKey); if (subDeser != null) { return subDeser; } @@ -1902,12 +1907,17 @@ protected JsonDeserializer _findSubclassDeserializer(DeserializationCont subDeser = ctxt.findRootValueDeserializer(type); // Also, need to cache it if (subDeser != null) { - synchronized (this) { - if (_subDeserializers == null) { - _subDeserializers = new HashMap>();; + if (_subDeserializers == null) { + _subDeserializersLock.lock(); + try { + if (_subDeserializers == null) { + _subDeserializers = new ConcurrentHashMap<>(); + } + } finally { + _subDeserializersLock.unlock(); } - _subDeserializers.put(new ClassKey(bean.getClass()), subDeser); } + _subDeserializers.put(classKey, subDeser); } return subDeser; } From b25e49eb85fa3cd86fd3053bd00d93403eeffd4b Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Thu, 28 Mar 2024 19:58:29 +0100 Subject: [PATCH 2/3] Update BeanDeserializerBase.java --- .../jackson/databind/deser/BeanDeserializerBase.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java index bb26443a8e..7e13496b1e 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java @@ -1891,13 +1891,13 @@ protected JsonDeserializer _findSubclassDeserializer(DeserializationCont throws IOException { // First: maybe we have already created sub-type deserializer? - ClassKey classKey = new ClassKey(bean.getClass()); + final ClassKey classKey = new ClassKey(bean.getClass()); JsonDeserializer subDeser = (_subDeserializers == null) ? null : _subDeserializers.get(classKey); if (subDeser != null) { return subDeser; } // If not, maybe we can locate one. First, need provider - JavaType type = ctxt.constructType(bean.getClass()); + final JavaType type = ctxt.constructType(bean.getClass()); /* 30-Jan-2012, tatu: Ideally we would be passing referring * property; which in theory we could keep track of via * ResolvableDeserializer (if we absolutely must...). From fdbb2dfb85f1ef2f81206aab668aa707f492e001 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Sun, 7 Apr 2024 14:10:06 +0200 Subject: [PATCH 3/3] remove lock --- .../jackson/databind/deser/BeanDeserializerBase.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java index 7e13496b1e..806d12b43f 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java @@ -5,7 +5,6 @@ import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.ReentrantLock; import com.fasterxml.jackson.annotation.*; @@ -183,11 +182,6 @@ public abstract class BeanDeserializerBase */ protected transient ConcurrentHashMap> _subDeserializers; - /** - * Lock used to prevent multiple creation of _subDeserializers map - */ - private final ReentrantLock _subDeserializersLock = new ReentrantLock(); - /** * If one of properties has "unwrapped" value, we need separate * helper object @@ -1908,13 +1902,10 @@ protected JsonDeserializer _findSubclassDeserializer(DeserializationCont // Also, need to cache it if (subDeser != null) { if (_subDeserializers == null) { - _subDeserializersLock.lock(); - try { + synchronized (this) { if (_subDeserializers == null) { _subDeserializers = new ConcurrentHashMap<>(); } - } finally { - _subDeserializersLock.unlock(); } } _subDeserializers.put(classKey, subDeser);