修复SafeConcurrentHashMap.computeIfAbsent可能存在的结果为null的情况

This commit is contained in:
Looly 2023-04-02 21:37:50 +08:00
parent 8ceaaa6428
commit 84e8456377
3 changed files with 41 additions and 19 deletions

View File

@ -2,7 +2,7 @@
# 🚀Changelog
-------------------------------------------------------------------------------------------------------------
# 5.8.17.M1 (2023-04-01)
# 5.8.17.M1 (2023-04-02)
### 🐣新特性
* 【core 】 SerializeUtil.deserialize增加白名单类避免RCE vulnerabilityissue#3021@Github
@ -17,6 +17,7 @@
### 🐞Bug修复
* 【core 】 CollUtil.split优化切割列表参数判断避免OOMpr#3026@Github
* 【core 】 修复FileUtil.move传入相同目录或子目录丢失源目录的问题pr#3032@Github
* 【core 】 修复SafeConcurrentHashMap.computeIfAbsent可能存在的结果为null的情况issue#I6RVMY@Gitee
-------------------------------------------------------------------------------------------------------------
# 5.8.16 (2023-03-26)

View File

@ -1481,17 +1481,46 @@ public class MapUtil {
*/
public static <K, V> V computeIfAbsent(Map<K, V> map, K key, Function<? super K, ? extends V> mappingFunction) {
if (JdkUtil.IS_JDK8) {
V value = map.get(key);
if (null == value) {
map.putIfAbsent(key, mappingFunction.apply(key));
value = map.get(key);
// 判空后调用依旧无法解决死循环问题
//value = map.computeIfAbsent(key, mappingFunction);
}
return value;
return computeIfAbsentForJdk8(map, key, mappingFunction);
} else {
return map.computeIfAbsent(key, mappingFunction);
}
}
/**
* 如果 key 对应的 value 不存在则使用获取 mappingFunction 重新计算后的值并保存为该 key value否则返回 value<br>
* 解决使用ConcurrentHashMap.computeIfAbsent导致的死循环问题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.
*
* <p>
* 注意此方法只能用于JDK8
* </p>
*
* @param <K> 键类型
* @param <V> 值类型
* @param map Map一般用于线程安全的Map
* @param key
* @param mappingFunction 值计算函数
* @return
* @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 computeIfAbsentForJdk8(final Map<K, V> map, final K key, final Function<? super K, ? extends V> mappingFunction) {
V value = map.get(key);
if (null == value) {
value = mappingFunction.apply(key);
final V res = map.putIfAbsent(key, value);
if(null != res){
// issues#I6RVMY
// 如果旧值存在说明其他线程已经赋值成功putIfAbsent没有执行返回旧值
return res;
}
// 如果旧值不存在说明赋值成功返回当前值
// Dubbo的解决方式判空后调用依旧无法解决死循环问题
// Issue2349Test
//value = map.computeIfAbsent(key, mappingFunction);
}
return value;
}
}

View File

@ -72,15 +72,7 @@ public class SafeConcurrentHashMap<K, V> extends ConcurrentHashMap<K, V> {
@Override
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
if (JdkUtil.IS_JDK8) {
V value = get(key);
if (null == value) {
putIfAbsent(key, mappingFunction.apply(key));
value = get(key);
// 判空后调用依旧无法解决死循环问题
//value = map.computeIfAbsent(key, mappingFunction);
}
return value;
return MapUtil.computeIfAbsentForJdk8(this, key, mappingFunction);
} else {
return super.computeIfAbsent(key, mappingFunction);
}