From dda421519080b85fd5b41a48352e4716177d316c Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Sun, 21 Mar 2021 19:31:25 +0100 Subject: [PATCH] [jOOQ/jOOQ#11684] Cannot use ConcurrentHashMap.computeIfAbsent() Because that would prevent calling it recursively due to an implementation flaw in the JDK method. --- jOOQ/src/main/java/org/jooq/impl/Tools.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index 76c50f9040..b3453534d5 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -3354,8 +3354,20 @@ final class Tools { if (cacheOrNull == NULL) return operation.get(); - // The cache is guaranteed to be thread safe by the CacheProvider contract - Object result = ((Map) cacheOrNull).computeIfAbsent(key.get(), k -> defaultIfNull(operation.get(), NULL)); + // The cache is guaranteed to be thread safe by the CacheProvider + // contract. However since we cannot use ConcurrentHashMap.computeIfAbsent() + // recursively, we have to revert to double checked locking nonetheless. + Map cache = (Map) cacheOrNull; + Object result = cache.get(key); + if (result == null) { + synchronized (cache) { + result = cache.get(key); + + if (result == null) + cache.put(key, (result = operation.get()) == null ? NULL : result); + } + } + return (V) (result == NULL ? null : result); }