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; }