From 23cdf8465cb3541435dbda2fc3bc17ce93678751 Mon Sep 17 00:00:00 2001 From: Rene Schakmann <108671777+rene-schakmann@users.noreply.github.com> Date: Fri, 2 Oct 2026 15:13:24 +0200 Subject: [PATCH] Clarify ConcurrentReferenceHashMap reference semantics Prior to this commit, the Javadoc for ConcurrentReferenceHashMap stated that soft or weak references are used for both keys and values. However, the references are applied to the internal map entries, each of which holds strong references to its key and value. Consequently, an entry may be discarded even if its key and value are still strongly reachable from elsewhere, which differs from the semantics of WeakHashMap. This commit revises the class-level Javadoc as well as the Javadoc for the ReferenceType constants to document this behavior. See gh-24253 Closes gh-37357 Signed-off-by: rene.schakmann --- .../util/ConcurrentReferenceHashMap.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/util/ConcurrentReferenceHashMap.java b/spring-core/src/main/java/org/springframework/util/ConcurrentReferenceHashMap.java index 808b57dbba9..21a3b6b3488 100644 --- a/spring-core/src/main/java/org/springframework/util/ConcurrentReferenceHashMap.java +++ b/spring-core/src/main/java/org/springframework/util/ConcurrentReferenceHashMap.java @@ -44,7 +44,7 @@ import org.jspecify.annotations.Nullable; /** * A {@link ConcurrentHashMap} variant that uses {@link ReferenceType#SOFT soft} or - * {@linkplain ReferenceType#WEAK weak} references for both {@code keys} and {@code values}. + * {@linkplain ReferenceType#WEAK weak} references for its entries. * *

This class can be used as an alternative to * {@code Collections.synchronizedMap(new WeakHashMap>())} in order to @@ -57,6 +57,16 @@ import org.jspecify.annotations.Nullable; * references at any time, so it may appear that an unknown thread is silently removing * entries. * + *

Note that the soft or weak references are applied to the internal entries of the + * map, not to the keys and values themselves: each entry holds strong references to its + * key and value, whereas the map only holds a soft or weak reference to the entry. + * Consequently, an entry may be discarded even if its key and value are still strongly + * reachable from elsewhere. In contrast to {@link java.util.WeakHashMap}, the lifetime + * of an entry is therefore not tied to the reachability of its key. In particular, with + * {@link ReferenceType#WEAK weak} references, entries are likely to be removed on the + * next garbage collection. This makes the map suitable for caches whose entries can be + * recomputed on demand, but not for associating data with a key for the key's lifetime. + * *

If not explicitly specified, this implementation will use * {@linkplain SoftReference soft entry references}. * @@ -599,10 +609,10 @@ public class ConcurrentReferenceHashMap extends AbstractMap implemen */ public enum ReferenceType { - /** Use {@link SoftReference SoftReferences}. */ + /** Use {@link SoftReference SoftReferences} for map entries. */ SOFT, - /** Use {@link WeakReference WeakReferences}. */ + /** Use {@link WeakReference WeakReferences} for map entries. */ WEAK }