diff --git a/core/src/main/java/hudson/util/XStream2.java b/core/src/main/java/hudson/util/XStream2.java index 5c6ebc566731..cf1b5e9bcaab 100644 --- a/core/src/main/java/hudson/util/XStream2.java +++ b/core/src/main/java/hudson/util/XStream2.java @@ -475,12 +475,8 @@ protected Class computeValue(Class type) { return computeConverterClass(type); } }; - private final ClassValue cache = new ClassValue() { - @Override - protected Converter computeValue(Class type) { - return computeConverter(type); - } - }; + private final ConcurrentHashMap, Converter> cache = + new ConcurrentHashMap<>(); private AssociatedConverterImpl(XStream xstream) { this.xstream = xstream; @@ -491,7 +487,9 @@ private Converter findConverter(@CheckForNull Class t) { if (t == null) { return null; } - return cache.get(t); + Converter result = cache.computeIfAbsent(t, unused -> computeConverter(t)); + // ConcurrentHashMap does not allow null, so use this object to represent null + return result == this ? null : result; } @CheckForNull @@ -515,7 +513,8 @@ private static Class computeConverterClass(@NonNull private Converter computeConverter(@NonNull Class t) { Class cl = classCache.get(t); if (cl == null) { - return null; + // See above.. this object in cache represents null + return this; } try { Constructor c = cl.getConstructors()[0];