修复ConcurrentHashMap.computeIfAbsent缺陷导致的问题

This commit is contained in:
Looly 2022-09-15 01:35:34 +08:00
parent 3fd1ebe0f5
commit 920fe44e50
5 changed files with 15 additions and 17 deletions

View File

@ -18,6 +18,7 @@
* 【db 】 修复Hive2驱动无法识别问题issue#2606@Github
* 【core 】 修复computeIfAbsent问题issue#I5PTN3@Gitee
* 【extra 】 修复Ftp中路径问题issue#I5R2DE@Gitee
* 【core 】 修复ConcurrentHashMap.computeIfAbsent缺陷导致的问题
-------------------------------------------------------------------------------------------------------------

View File

@ -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<BeanDesc> supplier) {
return bdCache.computeIfAbsent(beanClass, (key)->supplier.callWithRuntimeException());
return MapUtil.computeIfAbsent(bdCache, beanClass, (key)->supplier.callWithRuntimeException());
}
/**

View File

@ -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> T get(String key, Func0<T> 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());
}
/**

View File

@ -1464,17 +1464,19 @@ public class MapUtil {
}
/**
* 方法来自MyBatis解决使用ConcurrentHashMap.computeIfAbsent导致的死循环问题<br>
* 方法来自Dubbo解决使用ConcurrentHashMap.computeIfAbsent导致的死循环问题<br>
* issues#2349<br>
* A temporary workaround for Java 8 specific performance issue JDK-8161372 .<br>
* This class should be removed once we drop Java 8 support.
*
* @see <a href="https://bugs.openjdk.java.net/browse/JDK-8161372">https://bugs.openjdk.java.net/browse/JDK-8161372</a>
*/
public static <K, V> V computeIfAbsent(Map<K, V> map, K key, Function<K, V> 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;
}
}

View File

@ -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<String, Class<?>> PRIMITIVE_TYPE_NAME_MAP = new ConcurrentHashMap<>(32);
private static final WeakConcurrentMap<Pair<String, ClassLoader>, Class<?>> CLASS_CACHE = new WeakConcurrentMap<>();
private static final Map<Pair<String, ClassLoader>, Class<?>> CLASS_CACHE = new WeakConcurrentMap<>();
static {
List<Class<?>> 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;
}