From 1384bc8793ca1173631c3fa7dba1d31835daf6d5 Mon Sep 17 00:00:00 2001 From: Eduard Dudar Date: Wed, 3 Jan 2024 00:41:07 -0800 Subject: [PATCH 1/8] Added instantiators for additional container classes: LinkedList, HashSet, TreeSet, ConcurrentHashMap, and TreeMap. Replaced other new instantiator invocations with singletons. --- .../deser/impl/JDKValueInstantiators.java | 159 ++++++++++++++---- .../deser/std/JsonLocationInstantiator.java | 3 + 2 files changed, 130 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java index b3312aa31a..26f74dba90 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java @@ -2,6 +2,7 @@ import java.io.IOException; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import com.fasterxml.jackson.core.JsonLocation; @@ -23,7 +24,7 @@ public static ValueInstantiator findStdValueInstantiator(DeserializationConfig c Class raw) { if (raw == JsonLocation.class) { - return new JsonLocationInstantiator(); + return JsonLocationInstantiator.INSTANCE; } // [databind#1868]: empty List/Set/Map // [databind#2416]: optimize commonly needed default creators @@ -31,11 +32,20 @@ public static ValueInstantiator findStdValueInstantiator(DeserializationConfig c if (raw == ArrayList.class) { return ArrayListInstantiator.INSTANCE; } + if (raw == LinkedList.class) { + return LinkedListInstantiator.INSTANCE; + } + if (raw == HashSet.class) { + return HashSetInstantiator.INSTANCE; + } + if (raw == TreeSet.class) { + return TreeSetInstantiator.INSTANCE; + } if (Collections.EMPTY_SET.getClass() == raw) { - return new ConstantValueInstantiator(Collections.EMPTY_SET); + return ConstantValueInstantiator.EMPTY_SET; } if (Collections.EMPTY_LIST.getClass() == raw) { - return new ConstantValueInstantiator(Collections.EMPTY_LIST); + return ConstantValueInstantiator.EMPTY_LIST; } } else if (Map.class.isAssignableFrom(raw)) { if (raw == LinkedHashMap.class) { @@ -44,53 +54,129 @@ public static ValueInstantiator findStdValueInstantiator(DeserializationConfig c if (raw == HashMap.class) { return HashMapInstantiator.INSTANCE; } + if (raw == ConcurrentHashMap.class) { + return ConcurrentHashMapInstantiator.INSTANCE; + } + if (raw == TreeMap.class) { + return TreeMapInstantiator.INSTANCE; + } if (Collections.EMPTY_MAP.getClass() == raw) { - return new ConstantValueInstantiator(Collections.EMPTY_MAP); + return ConstantValueInstantiator.EMPTY_MAP; } } return null; } - private static class ArrayListInstantiator + private abstract static class JDKValueInstantiator extends ValueInstantiator.Base implements java.io.Serializable + { + public JDKValueInstantiator(Class type) { + super(type); + } + + @Override + public boolean canInstantiate() { return true; } + + @Override + public boolean canCreateUsingDefault() { return true; } + } + + private static class ArrayListInstantiator + extends JDKValueInstantiator { private static final long serialVersionUID = 2L; - public final static ArrayListInstantiator INSTANCE = new ArrayListInstantiator(); + public static final ArrayListInstantiator INSTANCE = new ArrayListInstantiator(); + public ArrayListInstantiator() { super(ArrayList.class); } @Override - public boolean canInstantiate() { return true; } + public Object createUsingDefault(DeserializationContext ctxt) throws IOException { + return new ArrayList<>(); + } + } + + private static class LinkedListInstantiator + extends JDKValueInstantiator + { + private static final long serialVersionUID = 2L; + + public static final LinkedListInstantiator INSTANCE = new LinkedListInstantiator(); + + public LinkedListInstantiator() { + super(LinkedList.class); + } @Override - public boolean canCreateUsingDefault() { return true; } + public Object createUsingDefault(DeserializationContext ctxt) throws IOException { + return new LinkedList<>(); + } + } + + private static class HashSetInstantiator + extends JDKValueInstantiator + { + private static final long serialVersionUID = 2L; + + public static final HashSetInstantiator INSTANCE = new HashSetInstantiator(); + + public HashSetInstantiator() { + super(HashSet.class); + } @Override public Object createUsingDefault(DeserializationContext ctxt) throws IOException { - return new ArrayList<>(); + return new HashSet<>(); } } - private static class HashMapInstantiator - extends ValueInstantiator.Base - implements java.io.Serializable + private static class TreeSetInstantiator + extends JDKValueInstantiator { private static final long serialVersionUID = 2L; - public final static HashMapInstantiator INSTANCE = new HashMapInstantiator(); + public static final TreeSetInstantiator INSTANCE = new TreeSetInstantiator(); - public HashMapInstantiator() { - super(HashMap.class); + public TreeSetInstantiator() { + super(TreeSet.class); } @Override - public boolean canInstantiate() { return true; } + public Object createUsingDefault(DeserializationContext ctxt) throws IOException { + return new TreeSet<>(); + } + } + + private static class ConcurrentHashMapInstantiator + extends JDKValueInstantiator + { + private static final long serialVersionUID = 2L; + + public static final ConcurrentHashMapInstantiator INSTANCE = new ConcurrentHashMapInstantiator(); + + public ConcurrentHashMapInstantiator() { + super(ConcurrentHashMap.class); + } @Override - public boolean canCreateUsingDefault() { return true; } + public Object createUsingDefault(DeserializationContext ctxt) throws IOException { + return new ConcurrentHashMap<>(); + } + } + + private static class HashMapInstantiator + extends JDKValueInstantiator + { + private static final long serialVersionUID = 2L; + + public static final HashMapInstantiator INSTANCE = new HashMapInstantiator(); + + public HashMapInstantiator() { + super(HashMap.class); + } @Override public Object createUsingDefault(DeserializationContext ctxt) throws IOException { @@ -99,35 +185,50 @@ public Object createUsingDefault(DeserializationContext ctxt) throws IOException } private static class LinkedHashMapInstantiator - extends ValueInstantiator.Base - implements java.io.Serializable + extends JDKValueInstantiator { private static final long serialVersionUID = 2L; - public final static LinkedHashMapInstantiator INSTANCE = new LinkedHashMapInstantiator(); + public static final LinkedHashMapInstantiator INSTANCE = new LinkedHashMapInstantiator(); public LinkedHashMapInstantiator() { super(LinkedHashMap.class); } @Override - public boolean canInstantiate() { return true; } + public Object createUsingDefault(DeserializationContext ctxt) throws IOException { + return new LinkedHashMap<>(); + } + } - @Override - public boolean canCreateUsingDefault() { return true; } + private static class TreeMapInstantiator + extends JDKValueInstantiator + { + private static final long serialVersionUID = 2L; + + public static final TreeMapInstantiator INSTANCE = new TreeMapInstantiator(); + + public TreeMapInstantiator() { + super(TreeMap.class); + } @Override public Object createUsingDefault(DeserializationContext ctxt) throws IOException { - return new LinkedHashMap<>(); + return new TreeMap<>(); } } private static class ConstantValueInstantiator - extends ValueInstantiator.Base - implements java.io.Serializable + extends JDKValueInstantiator { private static final long serialVersionUID = 2L; + public static final ConstantValueInstantiator EMPTY_SET = new ConstantValueInstantiator(Collections.EMPTY_SET); + + public static final ConstantValueInstantiator EMPTY_LIST = new ConstantValueInstantiator(Collections.EMPTY_LIST); + + public static final ConstantValueInstantiator EMPTY_MAP = new ConstantValueInstantiator(Collections.EMPTY_MAP); + protected final Object _value; public ConstantValueInstantiator(Object value) { @@ -135,12 +236,6 @@ public ConstantValueInstantiator(Object value) { _value = value; } - @Override // yes, since default ctor works - public boolean canInstantiate() { return true; } - - @Override - public boolean canCreateUsingDefault() { return true; } - @Override public Object createUsingDefault(DeserializationContext ctxt) throws IOException { return _value; diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java index 90b815dc4b..d45316d2ab 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java @@ -10,6 +10,7 @@ import com.fasterxml.jackson.databind.deser.CreatorProperty; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.deser.ValueInstantiator; +import com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators; /** * For {@link JsonLocation}, we should be able to just implement @@ -21,6 +22,8 @@ public class JsonLocationInstantiator { private static final long serialVersionUID = 1L; + public static final JsonLocationInstantiator INSTANCE = new JsonLocationInstantiator(); + public JsonLocationInstantiator() { super(JsonLocation.class); } From eaa4997119706bf8e56352c224571341c891e140 Mon Sep 17 00:00:00 2001 From: Eduard Dudar Date: Wed, 3 Jan 2024 00:50:22 -0800 Subject: [PATCH 2/8] Removed unused import --- .../jackson/databind/deser/std/JsonLocationInstantiator.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java index d45316d2ab..fcb8f5143d 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java @@ -10,7 +10,6 @@ import com.fasterxml.jackson.databind.deser.CreatorProperty; import com.fasterxml.jackson.databind.deser.SettableBeanProperty; import com.fasterxml.jackson.databind.deser.ValueInstantiator; -import com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators; /** * For {@link JsonLocation}, we should be able to just implement From 0f2787a031f960bc80ec1228c5e49e633d3ae0cb Mon Sep 17 00:00:00 2001 From: Eduard Dudar Date: Wed, 3 Jan 2024 09:39:39 -0800 Subject: [PATCH 3/8] Addressed review comments --- .../deser/impl/JDKValueInstantiators.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java index 26f74dba90..50d33b758f 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java @@ -42,10 +42,10 @@ public static ValueInstantiator findStdValueInstantiator(DeserializationConfig c return TreeSetInstantiator.INSTANCE; } if (Collections.EMPTY_SET.getClass() == raw) { - return ConstantValueInstantiator.EMPTY_SET; + return ConstantValueInstantiator.EMPTY_SET_INSTANCE; } if (Collections.EMPTY_LIST.getClass() == raw) { - return ConstantValueInstantiator.EMPTY_LIST; + return ConstantValueInstantiator.EMPTY_LIST_INSTANCE; } } else if (Map.class.isAssignableFrom(raw)) { if (raw == LinkedHashMap.class) { @@ -61,7 +61,7 @@ public static ValueInstantiator findStdValueInstantiator(DeserializationConfig c return TreeMapInstantiator.INSTANCE; } if (Collections.EMPTY_MAP.getClass() == raw) { - return ConstantValueInstantiator.EMPTY_MAP; + return ConstantValueInstantiator.EMPTY_MAP_INSTANCE; } } return null; @@ -99,6 +99,7 @@ public Object createUsingDefault(DeserializationContext ctxt) throws IOException } } + // @since 2.17 [databind#4299] Instantiators for additional container classes private static class LinkedListInstantiator extends JDKValueInstantiator { @@ -116,6 +117,7 @@ public Object createUsingDefault(DeserializationContext ctxt) throws IOException } } + // @since 2.17 [databind#4299] Instantiators for additional container classes private static class HashSetInstantiator extends JDKValueInstantiator { @@ -133,6 +135,7 @@ public Object createUsingDefault(DeserializationContext ctxt) throws IOException } } + // @since 2.17 [databind#4299] Instantiators for additional container classes private static class TreeSetInstantiator extends JDKValueInstantiator { @@ -150,6 +153,7 @@ public Object createUsingDefault(DeserializationContext ctxt) throws IOException } } + // @since 2.17 [databind#4299] Instantiators for additional container classes private static class ConcurrentHashMapInstantiator extends JDKValueInstantiator { @@ -201,6 +205,7 @@ public Object createUsingDefault(DeserializationContext ctxt) throws IOException } } + // @since 2.17 [databind#4299] Instantiators for additional container classes private static class TreeMapInstantiator extends JDKValueInstantiator { @@ -223,11 +228,14 @@ private static class ConstantValueInstantiator { private static final long serialVersionUID = 2L; - public static final ConstantValueInstantiator EMPTY_SET = new ConstantValueInstantiator(Collections.EMPTY_SET); + public static final ConstantValueInstantiator EMPTY_SET_INSTANCE + = new ConstantValueInstantiator(Collections.EMPTY_SET); - public static final ConstantValueInstantiator EMPTY_LIST = new ConstantValueInstantiator(Collections.EMPTY_LIST); + public static final ConstantValueInstantiator EMPTY_LIST_INSTANCE + = new ConstantValueInstantiator(Collections.EMPTY_LIST); - public static final ConstantValueInstantiator EMPTY_MAP = new ConstantValueInstantiator(Collections.EMPTY_MAP); + public static final ConstantValueInstantiator EMPTY_MAP_INSTANCE + = new ConstantValueInstantiator(Collections.EMPTY_MAP); protected final Object _value; From dcb6247f9f540bb647cbe62f72b9441385eeef1b Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Wed, 3 Jan 2024 15:20:59 -0800 Subject: [PATCH 4/8] Add missing serialVersionUID to resolve warning --- .../jackson/databind/deser/impl/JDKValueInstantiators.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java index 50d33b758f..817ef58dea 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java @@ -71,6 +71,8 @@ private abstract static class JDKValueInstantiator extends ValueInstantiator.Base implements java.io.Serializable { + private static final long serialVersionUID = 2L; + public JDKValueInstantiator(Class type) { super(type); } From 1260bbd7ede0508a57ec1cc1e491af2756343788 Mon Sep 17 00:00:00 2001 From: Eduard Dudar Date: Wed, 3 Jan 2024 20:32:18 -0800 Subject: [PATCH 5/8] Moved all non-default instantiators to lazy model --- .../deser/impl/JDKValueInstantiators.java | 134 ++++++++++++++---- .../deser/std/JsonLocationInstantiator.java | 9 +- 2 files changed, 114 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java index 817ef58dea..525dc30443 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java @@ -24,7 +24,7 @@ public static ValueInstantiator findStdValueInstantiator(DeserializationConfig c Class raw) { if (raw == JsonLocation.class) { - return JsonLocationInstantiator.INSTANCE; + return JsonLocationInstantiator.instance(); } // [databind#1868]: empty List/Set/Map // [databind#2416]: optimize commonly needed default creators @@ -33,19 +33,19 @@ public static ValueInstantiator findStdValueInstantiator(DeserializationConfig c return ArrayListInstantiator.INSTANCE; } if (raw == LinkedList.class) { - return LinkedListInstantiator.INSTANCE; + return LinkedListInstantiator.instance(); } if (raw == HashSet.class) { return HashSetInstantiator.INSTANCE; } if (raw == TreeSet.class) { - return TreeSetInstantiator.INSTANCE; + return TreeSetInstantiator.instance(); } - if (Collections.EMPTY_SET.getClass() == raw) { - return ConstantValueInstantiator.EMPTY_SET_INSTANCE; + if (raw == Collections.emptySet().getClass()) { + return EmptySetInstantiator.instance(); } - if (Collections.EMPTY_LIST.getClass() == raw) { - return ConstantValueInstantiator.EMPTY_LIST_INSTANCE; + if (raw == Collections.emptyList().getClass()) { + return EmptyListInstantiator.instance(); } } else if (Map.class.isAssignableFrom(raw)) { if (raw == LinkedHashMap.class) { @@ -55,13 +55,13 @@ public static ValueInstantiator findStdValueInstantiator(DeserializationConfig c return HashMapInstantiator.INSTANCE; } if (raw == ConcurrentHashMap.class) { - return ConcurrentHashMapInstantiator.INSTANCE; + return ConcurrentHashMapInstantiator.instance(); } if (raw == TreeMap.class) { - return TreeMapInstantiator.INSTANCE; + return TreeMapInstantiator.instance(); } - if (Collections.EMPTY_MAP.getClass() == raw) { - return ConstantValueInstantiator.EMPTY_MAP_INSTANCE; + if (raw == Collections.emptyMap().getClass()) { + return EmptyMapInstantiator.instance(); } } return null; @@ -89,7 +89,7 @@ private static class ArrayListInstantiator { private static final long serialVersionUID = 2L; - public static final ArrayListInstantiator INSTANCE = new ArrayListInstantiator(); + private static final ArrayListInstantiator INSTANCE = new ArrayListInstantiator(); public ArrayListInstantiator() { super(ArrayList.class); @@ -107,7 +107,14 @@ private static class LinkedListInstantiator { private static final long serialVersionUID = 2L; - public static final LinkedListInstantiator INSTANCE = new LinkedListInstantiator(); + private static LinkedListInstantiator _instance; + + private static LinkedListInstantiator instance() { + if (_instance == null) { + _instance = new LinkedListInstantiator(); + } + return _instance; + } public LinkedListInstantiator() { super(LinkedList.class); @@ -125,7 +132,7 @@ private static class HashSetInstantiator { private static final long serialVersionUID = 2L; - public static final HashSetInstantiator INSTANCE = new HashSetInstantiator(); + private static final HashSetInstantiator INSTANCE = new HashSetInstantiator(); public HashSetInstantiator() { super(HashSet.class); @@ -143,7 +150,14 @@ private static class TreeSetInstantiator { private static final long serialVersionUID = 2L; - public static final TreeSetInstantiator INSTANCE = new TreeSetInstantiator(); + private static TreeSetInstantiator _instance; + + private static TreeSetInstantiator instance() { + if (_instance == null) { + _instance = new TreeSetInstantiator(); + } + return _instance; + } public TreeSetInstantiator() { super(TreeSet.class); @@ -161,7 +175,14 @@ private static class ConcurrentHashMapInstantiator { private static final long serialVersionUID = 2L; - public static final ConcurrentHashMapInstantiator INSTANCE = new ConcurrentHashMapInstantiator(); + private static ConcurrentHashMapInstantiator _instance; + + private static ConcurrentHashMapInstantiator instance() { + if (_instance == null) { + _instance = new ConcurrentHashMapInstantiator(); + } + return _instance; + } public ConcurrentHashMapInstantiator() { super(ConcurrentHashMap.class); @@ -178,7 +199,7 @@ private static class HashMapInstantiator { private static final long serialVersionUID = 2L; - public static final HashMapInstantiator INSTANCE = new HashMapInstantiator(); + private static final HashMapInstantiator INSTANCE = new HashMapInstantiator(); public HashMapInstantiator() { super(HashMap.class); @@ -195,7 +216,7 @@ private static class LinkedHashMapInstantiator { private static final long serialVersionUID = 2L; - public static final LinkedHashMapInstantiator INSTANCE = new LinkedHashMapInstantiator(); + private static final LinkedHashMapInstantiator INSTANCE = new LinkedHashMapInstantiator(); public LinkedHashMapInstantiator() { super(LinkedHashMap.class); @@ -213,7 +234,14 @@ private static class TreeMapInstantiator { private static final long serialVersionUID = 2L; - public static final TreeMapInstantiator INSTANCE = new TreeMapInstantiator(); + private static TreeMapInstantiator _instance; + + private static TreeMapInstantiator instance() { + if (_instance == null) { + _instance = new TreeMapInstantiator(); + } + return _instance; + } public TreeMapInstantiator() { super(TreeMap.class); @@ -230,15 +258,6 @@ private static class ConstantValueInstantiator { private static final long serialVersionUID = 2L; - public static final ConstantValueInstantiator EMPTY_SET_INSTANCE - = new ConstantValueInstantiator(Collections.EMPTY_SET); - - public static final ConstantValueInstantiator EMPTY_LIST_INSTANCE - = new ConstantValueInstantiator(Collections.EMPTY_LIST); - - public static final ConstantValueInstantiator EMPTY_MAP_INSTANCE - = new ConstantValueInstantiator(Collections.EMPTY_MAP); - protected final Object _value; public ConstantValueInstantiator(Object value) { @@ -252,4 +271,63 @@ public Object createUsingDefault(DeserializationContext ctxt) throws IOException } } + // @since 2.17 [databind#4299] Instantiators for additional container classes + private static class EmptySetInstantiator + extends ConstantValueInstantiator + { + private static final long serialVersionUID = 2L; + + private static EmptySetInstantiator _instance; + + private static EmptySetInstantiator instance() { + if (_instance == null) { + _instance = new EmptySetInstantiator(); + } + return _instance; + } + + public EmptySetInstantiator() { + super(Collections.emptySet()); + } + } + + // @since 2.17 [databind#4299] Instantiators for additional container classes + private static class EmptyListInstantiator + extends ConstantValueInstantiator + { + private static final long serialVersionUID = 2L; + + private static EmptyListInstantiator _instance; + + private static EmptyListInstantiator instance() { + if (_instance == null) { + _instance = new EmptyListInstantiator(); + } + return _instance; + } + + public EmptyListInstantiator() { + super(Collections.emptyList()); + } + } + + // @since 2.17 [databind#4299] Instantiators for additional container classes + private static class EmptyMapInstantiator + extends ConstantValueInstantiator + { + private static final long serialVersionUID = 2L; + + private static EmptyMapInstantiator _instance; + + private static EmptyMapInstantiator instance() { + if (_instance == null) { + _instance = new EmptyMapInstantiator(); + } + return _instance; + } + + public EmptyMapInstantiator() { + super(Collections.emptyMap()); + } + } } diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java index fcb8f5143d..00ad2bf82c 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java @@ -21,7 +21,14 @@ public class JsonLocationInstantiator { private static final long serialVersionUID = 1L; - public static final JsonLocationInstantiator INSTANCE = new JsonLocationInstantiator(); + private static JsonLocationInstantiator _instance; + + public static JsonLocationInstantiator instance() { + if (_instance == null) { + _instance = new JsonLocationInstantiator(); + } + return _instance; + } public JsonLocationInstantiator() { super(JsonLocation.class); From 5c14fa4849225a07306c2d7620ff9d60d2a1b631 Mon Sep 17 00:00:00 2001 From: Eduard Dudar Date: Wed, 3 Jan 2024 20:35:21 -0800 Subject: [PATCH 6/8] Fixed indents --- .../jackson/databind/deser/impl/JDKValueInstantiators.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java index 525dc30443..3a94cc94f5 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java @@ -273,7 +273,7 @@ public Object createUsingDefault(DeserializationContext ctxt) throws IOException // @since 2.17 [databind#4299] Instantiators for additional container classes private static class EmptySetInstantiator - extends ConstantValueInstantiator + extends ConstantValueInstantiator { private static final long serialVersionUID = 2L; @@ -293,7 +293,7 @@ public EmptySetInstantiator() { // @since 2.17 [databind#4299] Instantiators for additional container classes private static class EmptyListInstantiator - extends ConstantValueInstantiator + extends ConstantValueInstantiator { private static final long serialVersionUID = 2L; @@ -313,7 +313,7 @@ public EmptyListInstantiator() { // @since 2.17 [databind#4299] Instantiators for additional container classes private static class EmptyMapInstantiator - extends ConstantValueInstantiator + extends ConstantValueInstantiator { private static final long serialVersionUID = 2L; From 2982e5682d27f879336b37ca0dc5b631a3eb0350 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Mon, 15 Jan 2024 21:02:18 -0800 Subject: [PATCH 7/8] Remove pre-creation/lazy-creation for non-default Collection/Map types --- release-notes/CREDITS-2.x | 4 + release-notes/VERSION-2.x | 2 + .../deser/impl/JDKValueInstantiators.java | 126 +++--------------- 3 files changed, 21 insertions(+), 111 deletions(-) diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x index 3a1968556b..e1e109bcdf 100644 --- a/release-notes/CREDITS-2.x +++ b/release-notes/CREDITS-2.x @@ -1738,3 +1738,7 @@ Muhammad Khalikov (mukham12@github) * Contributed fix for #4209: Make `BeanDeserializerModifier`/`BeanSerializerModifier` implement `java.io.Serializable` (2.17.0) + +Eduard Dudar (edudar@github) + * Contributed #4299: Some `Collection` and `Map` fallbacks don't work in GraalVM native image + (2.17.0) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 763a595b6d..aa2ddf1b49 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -31,6 +31,8 @@ Project: jackson-databind #4262: Improve handling of `null` insertion failure for `TreeSet` #4263: Change `ObjectArrayDeserializer` to use "generic" type parameter (`java.lang.Object`) to remove co-variant return type +#4299: Some `Collection` and `Map` fallbacks don't work in GraalVM native image + (contributed by Eduard D) #4309: `@JsonSetter(nulls=...)` handling of `Collection` `null` values during deserialization with `READ_UNKNOWN_ENUM_VALUES_AS_NULL` and `FAIL_ON_INVALID_SUBTYPE` wrong (reported by @ivan-zaitsev) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java index d0f5223e61..297ba8a613 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java @@ -24,28 +24,28 @@ public static ValueInstantiator findStdValueInstantiator(DeserializationConfig c Class raw) { if (raw == JsonLocation.class) { - return JsonLocationInstantiator.instance(); + return new JsonLocationInstantiator(); } // [databind#1868]: empty List/Set/Map // [databind#2416]: optimize commonly needed default creators if (Collection.class.isAssignableFrom(raw)) { - if (raw == ArrayList.class) { + if (raw == ArrayList.class) { // default impl, pre-constructed instance return ArrayListInstantiator.INSTANCE; } if (raw == LinkedList.class) { - return LinkedListInstantiator.instance(); + return new LinkedListInstantiator(); } - if (raw == HashSet.class) { + if (raw == HashSet.class) { // default impl, pre-constructed instance return HashSetInstantiator.INSTANCE; } if (raw == TreeSet.class) { - return TreeSetInstantiator.instance(); + return new TreeSetInstantiator(); } if (raw == Collections.emptySet().getClass()) { - return EmptySetInstantiator.instance(); + return new ConstantValueInstantiator(Collections.emptySet()); } if (raw == Collections.emptyList().getClass()) { - return EmptyListInstantiator.instance(); + return new ConstantValueInstantiator(Collections.emptyList()); } } else if (Map.class.isAssignableFrom(raw)) { if (raw == LinkedHashMap.class) { @@ -55,13 +55,13 @@ public static ValueInstantiator findStdValueInstantiator(DeserializationConfig c return HashMapInstantiator.INSTANCE; } if (raw == ConcurrentHashMap.class) { - return ConcurrentHashMapInstantiator.instance(); + return new ConcurrentHashMapInstantiator(); } if (raw == TreeMap.class) { - return TreeMapInstantiator.instance(); + return new TreeMapInstantiator(); } if (raw == Collections.emptyMap().getClass()) { - return EmptyMapInstantiator.instance(); + return new ConstantValueInstantiator(Collections.emptyMap()); } } return null; @@ -93,7 +93,7 @@ private static class ArrayListInstantiator { private static final long serialVersionUID = 2L; - private static final ArrayListInstantiator INSTANCE = new ArrayListInstantiator(); + static final ArrayListInstantiator INSTANCE = new ArrayListInstantiator(); public ArrayListInstantiator() { super(ArrayList.class); @@ -111,15 +111,6 @@ private static class LinkedListInstantiator { private static final long serialVersionUID = 2L; - private static LinkedListInstantiator _instance; - - private static LinkedListInstantiator instance() { - if (_instance == null) { - _instance = new LinkedListInstantiator(); - } - return _instance; - } - public LinkedListInstantiator() { super(LinkedList.class); } @@ -136,7 +127,7 @@ private static class HashSetInstantiator { private static final long serialVersionUID = 2L; - private static final HashSetInstantiator INSTANCE = new HashSetInstantiator(); + static final HashSetInstantiator INSTANCE = new HashSetInstantiator(); public HashSetInstantiator() { super(HashSet.class); @@ -154,15 +145,6 @@ private static class TreeSetInstantiator { private static final long serialVersionUID = 2L; - private static TreeSetInstantiator _instance; - - private static TreeSetInstantiator instance() { - if (_instance == null) { - _instance = new TreeSetInstantiator(); - } - return _instance; - } - public TreeSetInstantiator() { super(TreeSet.class); } @@ -179,15 +161,6 @@ private static class ConcurrentHashMapInstantiator { private static final long serialVersionUID = 2L; - private static ConcurrentHashMapInstantiator _instance; - - private static ConcurrentHashMapInstantiator instance() { - if (_instance == null) { - _instance = new ConcurrentHashMapInstantiator(); - } - return _instance; - } - public ConcurrentHashMapInstantiator() { super(ConcurrentHashMap.class); } @@ -203,7 +176,7 @@ private static class HashMapInstantiator { private static final long serialVersionUID = 2L; - private static final HashMapInstantiator INSTANCE = new HashMapInstantiator(); + static final HashMapInstantiator INSTANCE = new HashMapInstantiator(); public HashMapInstantiator() { super(HashMap.class); @@ -220,7 +193,7 @@ private static class LinkedHashMapInstantiator { private static final long serialVersionUID = 2L; - private static final LinkedHashMapInstantiator INSTANCE = new LinkedHashMapInstantiator(); + static final LinkedHashMapInstantiator INSTANCE = new LinkedHashMapInstantiator(); public LinkedHashMapInstantiator() { super(LinkedHashMap.class); @@ -238,15 +211,6 @@ private static class TreeMapInstantiator { private static final long serialVersionUID = 2L; - private static TreeMapInstantiator _instance; - - private static TreeMapInstantiator instance() { - if (_instance == null) { - _instance = new TreeMapInstantiator(); - } - return _instance; - } - public TreeMapInstantiator() { super(TreeMap.class); } @@ -270,68 +234,8 @@ public ConstantValueInstantiator(Object value) { } @Override - public Object createUsingDefault(DeserializationContext ctxt) throws IOException { + public final Object createUsingDefault(DeserializationContext ctxt) throws IOException { return _value; } } - - // @since 2.17 [databind#4299] Instantiators for additional container classes - private static class EmptySetInstantiator - extends ConstantValueInstantiator - { - private static final long serialVersionUID = 2L; - - private static EmptySetInstantiator _instance; - - private static EmptySetInstantiator instance() { - if (_instance == null) { - _instance = new EmptySetInstantiator(); - } - return _instance; - } - - public EmptySetInstantiator() { - super(Collections.emptySet()); - } - } - - // @since 2.17 [databind#4299] Instantiators for additional container classes - private static class EmptyListInstantiator - extends ConstantValueInstantiator - { - private static final long serialVersionUID = 2L; - - private static EmptyListInstantiator _instance; - - private static EmptyListInstantiator instance() { - if (_instance == null) { - _instance = new EmptyListInstantiator(); - } - return _instance; - } - - public EmptyListInstantiator() { - super(Collections.emptyList()); - } - } - - // @since 2.17 [databind#4299] Instantiators for additional container classes - private static class EmptyMapInstantiator - extends ConstantValueInstantiator - { - private static final long serialVersionUID = 2L; - - private static EmptyMapInstantiator _instance; - - private static EmptyMapInstantiator instance() { - if (_instance == null) { - _instance = new EmptyMapInstantiator(); - } - return _instance; - } - - public EmptyMapInstantiator() { - super(Collections.emptyMap()); - } - } } From 8e13fd4d09915643e584d2222ee096633f71c7c7 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Mon, 15 Jan 2024 21:05:20 -0800 Subject: [PATCH 8/8] Remove one unnecessary pre-created instance --- .../databind/deser/impl/JDKValueInstantiators.java | 7 ++++--- .../databind/deser/std/JsonLocationInstantiator.java | 9 --------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java index 297ba8a613..4e6788fdc8 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java @@ -32,12 +32,12 @@ public static ValueInstantiator findStdValueInstantiator(DeserializationConfig c if (raw == ArrayList.class) { // default impl, pre-constructed instance return ArrayListInstantiator.INSTANCE; } - if (raw == LinkedList.class) { - return new LinkedListInstantiator(); - } if (raw == HashSet.class) { // default impl, pre-constructed instance return HashSetInstantiator.INSTANCE; } + if (raw == LinkedList.class) { + return new LinkedListInstantiator(); + } if (raw == TreeSet.class) { return new TreeSetInstantiator(); } @@ -67,6 +67,7 @@ public static ValueInstantiator findStdValueInstantiator(DeserializationConfig c return null; } + // @since 2.17 private abstract static class JDKValueInstantiator extends ValueInstantiator.Base implements java.io.Serializable diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java index 00ad2bf82c..90b815dc4b 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java @@ -21,15 +21,6 @@ public class JsonLocationInstantiator { private static final long serialVersionUID = 1L; - private static JsonLocationInstantiator _instance; - - public static JsonLocationInstantiator instance() { - if (_instance == null) { - _instance = new JsonLocationInstantiator(); - } - return _instance; - } - public JsonLocationInstantiator() { super(JsonLocation.class); }