From 920fe44e50e23c19457704ad4313e7d93a2b3fd3 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 15 Sep 2022 01:35:34 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DConcurrentHashMap.computeIfAb?= =?UTF-8?q?sent=E7=BC=BA=E9=99=B7=E5=AF=BC=E8=87=B4=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + .../main/java/cn/hutool/core/bean/BeanDescCache.java | 3 ++- .../src/main/java/cn/hutool/core/lang/Singleton.java | 11 ++--------- .../src/main/java/cn/hutool/core/map/MapUtil.java | 12 +++++++----- .../java/cn/hutool/core/util/ClassLoaderUtil.java | 5 +++-- 5 files changed, 15 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88771f6c5..c28f6fc09 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ * 【db 】 修复Hive2驱动无法识别问题(issue#2606@Github) * 【core 】 修复computeIfAbsent问题(issue#I5PTN3@Gitee) * 【extra 】 修复Ftp中路径问题(issue#I5R2DE@Gitee) +* 【core 】 修复ConcurrentHashMap.computeIfAbsent缺陷导致的问题 ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/BeanDescCache.java b/hutool-core/src/main/java/cn/hutool/core/bean/BeanDescCache.java index fa29e1d94..3cd993dcf 100755 --- a/hutool-core/src/main/java/cn/hutool/core/bean/BeanDescCache.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/BeanDescCache.java @@ -1,6 +1,7 @@ package cn.hutool.core.bean; import cn.hutool.core.lang.func.Func0; +import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.WeakConcurrentMap; /** @@ -23,7 +24,7 @@ public enum BeanDescCache { * @since 5.4.2 */ public BeanDesc getBeanDesc(Class beanClass, Func0 supplier) { - return bdCache.computeIfAbsent(beanClass, (key)->supplier.callWithRuntimeException()); + return MapUtil.computeIfAbsent(bdCache, beanClass, (key)->supplier.callWithRuntimeException()); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/Singleton.java b/hutool-core/src/main/java/cn/hutool/core/lang/Singleton.java index ab26a662b..5d5c1066e 100755 --- a/hutool-core/src/main/java/cn/hutool/core/lang/Singleton.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/Singleton.java @@ -1,6 +1,7 @@ package cn.hutool.core.lang; import cn.hutool.core.lang.func.Func0; +import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ClassUtil; import cn.hutool.core.util.ReflectUtil; @@ -52,15 +53,7 @@ public final class Singleton { */ @SuppressWarnings("unchecked") public static T get(String key, Func0 supplier) { - //return (T) POOL.computeIfAbsent(key, (k)-> supplier.callWithRuntimeException()); - // issues#2349 - // ConcurrentHashMap.computeIfAbsent在某些情况下会导致死循环问题,此处采用Dubbo的解决方案 - Object value = POOL.get(key); - if(null == value){ - POOL.putIfAbsent(key, supplier.callWithRuntimeException()); - value = POOL.get(key); - } - return (T) value; + return (T) MapUtil.computeIfAbsent(POOL, key, (k)-> supplier.callWithRuntimeException()); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/map/MapUtil.java b/hutool-core/src/main/java/cn/hutool/core/map/MapUtil.java index 2c13bd22a..e6a28b297 100755 --- a/hutool-core/src/main/java/cn/hutool/core/map/MapUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/MapUtil.java @@ -1464,17 +1464,19 @@ public class MapUtil { } /** - * 方法来自MyBatis,解决使用ConcurrentHashMap.computeIfAbsent导致的死循环问题。
+ * 方法来自Dubbo,解决使用ConcurrentHashMap.computeIfAbsent导致的死循环问题。
+ * issues#2349
* A temporary workaround for Java 8 specific performance issue JDK-8161372 .
* This class should be removed once we drop Java 8 support. * * @see https://bugs.openjdk.java.net/browse/JDK-8161372 */ public static V computeIfAbsent(Map map, K key, Function mappingFunction) { - final V value = map.get(key); - if (value != null) { - return value; + V value = map.get(key); + if(null == value){ + map.putIfAbsent(key, mappingFunction.apply(key)); + value = map.get(key); } - return map.computeIfAbsent(key, mappingFunction); + return value; } } diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ClassLoaderUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ClassLoaderUtil.java index 2300fe107..aeae12b84 100755 --- a/hutool-core/src/main/java/cn/hutool/core/util/ClassLoaderUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ClassLoaderUtil.java @@ -5,6 +5,7 @@ import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.JarClassLoader; import cn.hutool.core.lang.Pair; +import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.WeakConcurrentMap; import cn.hutool.core.text.CharPool; @@ -50,7 +51,7 @@ public class ClassLoaderUtil { * 原始类型名和其class对应表,例如:int =》 int.class */ private static final Map> PRIMITIVE_TYPE_NAME_MAP = new ConcurrentHashMap<>(32); - private static final WeakConcurrentMap, Class> CLASS_CACHE = new WeakConcurrentMap<>(); + private static final Map, Class> CLASS_CACHE = new WeakConcurrentMap<>(); static { List> primitiveTypes = new ArrayList<>(32); @@ -199,7 +200,7 @@ public class ClassLoaderUtil { if (clazz == null) { final String finalName = name; final ClassLoader finalClassLoader = classLoader; - clazz = CLASS_CACHE.computeIfAbsent(Pair.of(name, classLoader), (key)-> doLoadClass(finalName, finalClassLoader, isInitialized)); + clazz = MapUtil.computeIfAbsent(CLASS_CACHE, Pair.of(name, classLoader), (key)-> doLoadClass(finalName, finalClassLoader, isInitialized)); } return clazz; }