Skip to content

Commit 9577138

Browse files
committed
Fix #2416
1 parent 985ee58 commit 9577138

File tree

6 files changed

+133
-66
lines changed

6 files changed

+133
-66
lines changed

release-notes/VERSION-2.x

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Project: jackson-databind
1414
(reported by andreasbaus@github)
1515
#2393: `TreeTraversingParser.getLongValue()` incorrectly checks `canConvertToInt()`
1616
(reported by RabbidDog@github)
17+
#2416: Optimize `ValueInstantiator` construction for default `Collection`, `Map` types
1718

1819
2.10.0.pr1 (19-Jul-2019)
1920

src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java

+2-26
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
1111
import com.fasterxml.jackson.annotation.JsonCreator.Mode;
1212

13-
import com.fasterxml.jackson.core.JsonLocation;
1413
import com.fasterxml.jackson.core.JsonParser;
1514

1615
import com.fasterxml.jackson.databind.*;
1716
import com.fasterxml.jackson.databind.cfg.DeserializerFactoryConfig;
1817
import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
1918
import com.fasterxml.jackson.databind.deser.impl.CreatorCandidate;
2019
import com.fasterxml.jackson.databind.deser.impl.CreatorCollector;
20+
import com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators;
2121
import com.fasterxml.jackson.databind.deser.impl.JavaUtilCollectionsDeserializers;
2222
import com.fasterxml.jackson.databind.deser.std.*;
2323
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
@@ -216,7 +216,7 @@ public ValueInstantiator findValueInstantiator(DeserializationContext ctxt,
216216
if (instantiator == null) {
217217
// Second: see if some of standard Jackson/JDK types might provide value
218218
// instantiators.
219-
instantiator = _findStdValueInstantiator(config, beanDesc);
219+
instantiator = JDKValueInstantiators.findStdValueInstantiator(config, beanDesc.getBeanClass());
220220
if (instantiator == null) {
221221
instantiator = _constructDefaultValueInstantiator(ctxt, beanDesc);
222222
}
@@ -246,30 +246,6 @@ public ValueInstantiator findValueInstantiator(DeserializationContext ctxt,
246246
return instantiator;
247247
}
248248

249-
private ValueInstantiator _findStdValueInstantiator(DeserializationConfig config,
250-
BeanDescription beanDesc)
251-
throws JsonMappingException
252-
{
253-
Class<?> raw = beanDesc.getBeanClass();
254-
if (raw == JsonLocation.class) {
255-
return new JsonLocationInstantiator();
256-
}
257-
// [databind#1868]: empty List/Set/Map
258-
if (Collection.class.isAssignableFrom(raw)) {
259-
if (Collections.EMPTY_SET.getClass() == raw) {
260-
return new ConstantValueInstantiator(Collections.EMPTY_SET);
261-
}
262-
if (Collections.EMPTY_LIST.getClass() == raw) {
263-
return new ConstantValueInstantiator(Collections.EMPTY_LIST);
264-
}
265-
} else if (Map.class.isAssignableFrom(raw)) {
266-
if (Collections.EMPTY_MAP.getClass() == raw) {
267-
return new ConstantValueInstantiator(Collections.EMPTY_MAP);
268-
}
269-
}
270-
return null;
271-
}
272-
273249
/**
274250
* Method that will construct standard default {@link ValueInstantiator}
275251
* using annotations (like @JsonCreator) and visibility rules

src/main/java/com/fasterxml/jackson/databind/deser/ValueInstantiator.java

+3
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,10 @@ public interface Gettable {
397397
* to be used instead of directly extending {@link ValueInstantiator} itself.
398398
*/
399399
public static class Base extends ValueInstantiator
400+
implements java.io.Serializable // just because used as base for "standard" variants
400401
{
402+
private static final long serialVersionUID = 1L;
403+
401404
protected final Class<?> _valueType;
402405

403406
public Base(Class<?> type) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package com.fasterxml.jackson.databind.deser.impl;
2+
3+
import java.io.IOException;
4+
import java.util.ArrayList;
5+
import java.util.Collection;
6+
import java.util.Collections;
7+
import java.util.LinkedHashMap;
8+
import java.util.Map;
9+
10+
import com.fasterxml.jackson.core.JsonLocation;
11+
import com.fasterxml.jackson.databind.DeserializationConfig;
12+
import com.fasterxml.jackson.databind.DeserializationContext;
13+
import com.fasterxml.jackson.databind.deser.ValueInstantiator;
14+
import com.fasterxml.jackson.databind.deser.std.JsonLocationInstantiator;
15+
16+
/**
17+
* Container for a set of {@link ValueInstantiator}s used for certain critical
18+
* JDK value types, either as performance optimization for initialization time observed
19+
* by profiling, or due to difficulty in otherwise finding constructors.
20+
*
21+
* @since 2.10
22+
*/
23+
public abstract class JDKValueInstantiators
24+
{
25+
public static ValueInstantiator findStdValueInstantiator(DeserializationConfig config,
26+
Class<?> raw)
27+
{
28+
if (raw == JsonLocation.class) {
29+
return new JsonLocationInstantiator();
30+
}
31+
// [databind#1868]: empty List/Set/Map
32+
if (Collection.class.isAssignableFrom(raw)) {
33+
if (raw == ArrayList.class) {
34+
return ArrayListInstantiator.INSTANCE;
35+
}
36+
// [databind#XXX]: optimize commonly needed default creators
37+
if (Collections.EMPTY_SET.getClass() == raw) {
38+
return new ConstantValueInstantiator(Collections.EMPTY_SET);
39+
}
40+
if (Collections.EMPTY_LIST.getClass() == raw) {
41+
return new ConstantValueInstantiator(Collections.EMPTY_LIST);
42+
}
43+
} else if (Map.class.isAssignableFrom(raw)) {
44+
if (raw == LinkedHashMap.class) {
45+
return LinkedHashMapInstantiator.INSTANCE;
46+
}
47+
if (Collections.EMPTY_MAP.getClass() == raw) {
48+
return new ConstantValueInstantiator(Collections.EMPTY_MAP);
49+
}
50+
}
51+
return null;
52+
}
53+
54+
private static class ArrayListInstantiator
55+
extends ValueInstantiator.Base
56+
implements java.io.Serializable
57+
{
58+
private static final long serialVersionUID = 2L;
59+
60+
public final static ArrayListInstantiator INSTANCE = new ArrayListInstantiator();
61+
public ArrayListInstantiator() {
62+
super(ArrayList.class);
63+
}
64+
65+
@Override
66+
public boolean canInstantiate() { return true; }
67+
68+
@Override
69+
public boolean canCreateUsingDefault() { return true; }
70+
71+
@Override
72+
public Object createUsingDefault(DeserializationContext ctxt) throws IOException {
73+
return new ArrayList<>();
74+
}
75+
}
76+
77+
private static class LinkedHashMapInstantiator
78+
extends ValueInstantiator.Base
79+
implements java.io.Serializable
80+
{
81+
private static final long serialVersionUID = 2L;
82+
83+
public final static LinkedHashMapInstantiator INSTANCE = new LinkedHashMapInstantiator();
84+
85+
public LinkedHashMapInstantiator() {
86+
super(LinkedHashMap.class);
87+
}
88+
89+
@Override
90+
public boolean canInstantiate() { return true; }
91+
92+
@Override
93+
public boolean canCreateUsingDefault() { return true; }
94+
95+
@Override
96+
public Object createUsingDefault(DeserializationContext ctxt) throws IOException {
97+
return new LinkedHashMap<>();
98+
}
99+
}
100+
101+
private static class ConstantValueInstantiator
102+
extends ValueInstantiator.Base
103+
implements java.io.Serializable
104+
{
105+
private static final long serialVersionUID = 2L;
106+
107+
protected final Object _value;
108+
109+
public ConstantValueInstantiator(Object value) {
110+
super(value.getClass());
111+
_value = value;
112+
}
113+
114+
@Override // yes, since default ctor works
115+
public boolean canInstantiate() { return true; }
116+
117+
@Override
118+
public boolean canCreateUsingDefault() { return true; }
119+
120+
@Override
121+
public Object createUsingDefault(DeserializationContext ctxt) throws IOException {
122+
return _value;
123+
}
124+
}
125+
126+
}

src/main/java/com/fasterxml/jackson/databind/introspect/BasicClassIntrospector.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,7 @@ public BasicBeanDescription forCreation(DeserializationConfig cfg,
137137
{
138138
BasicBeanDescription desc = _findStdTypeDesc(type);
139139
if (desc == null) {
140-
141-
// As per [Databind#550], skip full introspection for some of standard
140+
// As per [databind#550], skip full introspection for some of standard
142141
// structured types as well
143142
desc = _findStdJdkCollectionDesc(cfg, type);
144143
if (desc == null) {

src/main/java/com/fasterxml/jackson/databind/util/ConstantValueInstantiator.java

-38
This file was deleted.

0 commit comments

Comments
 (0)