Skip to content

Commit 141d09b

Browse files
committed
Fix #1995 (with bound of 4000 cached deserializers)
1 parent 3fd96e8 commit 141d09b

File tree

3 files changed

+26
-17
lines changed

3 files changed

+26
-17
lines changed

release-notes/VERSION

+1
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,5 @@ Versions: 3.x (for earlier see VERSION-2.x)
3333
#1973: Remove support for "default [Map] key serializer" configuration from
3434
`SerializerProvider`
3535
#1994: Limit size of `SerializerCache`, auto-flush on exceeding
36+
#1995: Limit size of `DeserializerCache`, auto-flush on exceeding
3637
- Remove `MappingJsonFactory`

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

+23-16
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.fasterxml.jackson.databind.deser;
22

33
import java.util.HashMap;
4-
import java.util.concurrent.ConcurrentHashMap;
54

65
import com.fasterxml.jackson.annotation.JsonFormat;
76

@@ -12,10 +11,10 @@
1211
import com.fasterxml.jackson.databind.type.*;
1312
import com.fasterxml.jackson.databind.util.ClassUtil;
1413
import com.fasterxml.jackson.databind.util.Converter;
14+
import com.fasterxml.jackson.databind.util.SimpleLookupCache;
1515

1616
/**
17-
* Class that defines caching layer between callers (like
18-
* {@link ObjectMapper},
17+
* Class that defines caching layer between callers (like {@link ObjectMapper},
1918
* {@link com.fasterxml.jackson.databind.DeserializationContext})
2019
* and classes that construct deserializers
2120
* ({@link com.fasterxml.jackson.databind.deser.DeserializerFactory}).
@@ -25,6 +24,11 @@ public final class DeserializerCache
2524
{
2625
private static final long serialVersionUID = 3L;
2726

27+
/**
28+
* By default allow caching of up to 4000 deserializers.
29+
*/
30+
public final static int DEFAULT_MAX_CACHED = 4000;
31+
2832
/*
2933
/**********************************************************************
3034
/* Caching
@@ -34,42 +38,45 @@ public final class DeserializerCache
3438
/**
3539
* We will also cache some dynamically constructed deserializers;
3640
* specifically, ones that are expensive to construct.
37-
* This currently means bean and Enum deserializers; starting with
38-
* 2.5, container deserializers will also be cached.
39-
*<p>
40-
* Given that we don't expect much concurrency for additions
41-
* (should very quickly converge to zero after startup), let's
42-
* define a relatively low concurrency setting.
41+
* This currently (3.0) means POJO, Enum and Container (collection,
42+
* map) deserializers.
4343
*/
44-
private final transient ConcurrentHashMap<JavaType, JsonDeserializer<Object>> _cachedDeserializers
45-
= new ConcurrentHashMap<JavaType, JsonDeserializer<Object>>(64, 0.75f, 4);
44+
private final SimpleLookupCache<JavaType, JsonDeserializer<Object>> _cachedDeserializers;
4645

4746
/**
4847
* During deserializer construction process we may need to keep track of partially
4948
* completed deserializers, to resolve cyclic dependencies. This is the
5049
* map used for storing deserializers before they are fully complete.
5150
*/
5251
private final transient HashMap<JavaType, JsonDeserializer<Object>> _incompleteDeserializers
53-
= new HashMap<JavaType, JsonDeserializer<Object>>(8);
52+
= new HashMap<>(8);
5453

5554
/*
5655
/**********************************************************************
5756
/* Life-cycle
5857
/**********************************************************************
5958
*/
6059

61-
public DeserializerCache() { }
60+
public DeserializerCache() { this(DEFAULT_MAX_CACHED); }
61+
62+
public DeserializerCache(int maxSize) {
63+
int initial = Math.min(64, maxSize>>2);
64+
_cachedDeserializers = new SimpleLookupCache<>(initial, maxSize);
65+
}
66+
67+
private DeserializerCache(DeserializerCache src) {
68+
_cachedDeserializers = src._cachedDeserializers;
69+
}
6270

6371
/*
6472
/**********************************************************************
6573
/* JDK serialization handling
6674
/**********************************************************************
6775
*/
6876

69-
// 11-Apr-2018, tatu: instead of clearing or such on write, keep everything transient,
70-
// recreate as empty. No point trying to revive cached instances
77+
// Need to re-create just to initialize `transient` fields
7178
protected Object readResolve() {
72-
return new DeserializerCache();
79+
return new DeserializerCache(this);
7380
}
7481

7582
/*

src/main/java/com/fasterxml/jackson/databind/ser/SerializerCache.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ public SerializerCache() {
5353
* @since 3.0
5454
*/
5555
public SerializerCache(int maxCached) {
56-
_sharedMap = new SimpleLookupCache<TypeKey, JsonSerializer<Object>>(maxCached>>2, maxCached);
56+
int initial = Math.min(64, maxCached>>2);
57+
_sharedMap = new SimpleLookupCache<TypeKey, JsonSerializer<Object>>(initial, maxCached);
5758
_readOnlyMap = new AtomicReference<ReadOnlyClassToSerializerMap>();
5859
}
5960

0 commit comments

Comments
 (0)