From a504fa860c3cca148688e9778704fd712094fe2c Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 20 Jun 2025 17:34:24 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D`AbstractCache`putWithoutLock?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E5=8F=AF=E8=83=BD=E5=AF=BC=E8=87=B4=E7=9A=84?= =?UTF-8?q?=E5=A4=96=E9=83=A8=E8=B5=84=E6=BA=90=E6=B3=84=E9=9C=B2=E9=97=AE?= =?UTF-8?q?=E9=A2=98=EF=BC=88pr#3958@Github=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + .../cn/hutool/cache/impl/AbstractCache.java | 10 ++++------ .../test/java/cn/hutool/cache/CacheTest.java | 18 +++++++----------- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 467a40e93..5a471e161 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ * 【core 】 修复`ClassUti`isNormalClass判断未排除String问题(issue#3965@Github) * 【core 】 修复`ZipUtil`中zlib和unZlib调用后资源未释放问题(issue#3976@Github) * 【core 】 修复`Money`类的setAmount方法没有获取当前币种的小数位数而是使用的默认小数位和在遇到非2小数位的币种(如日元使用 0 位)会导致金额设置错误问题(pr#3970@Github) +* 【cahce 】 修复`AbstractCache`putWithoutLock方法可能导致的外部资源泄露问题(pr#3958@Github) ------------------------------------------------------------------------------------------------------------- # 5.8.38(2025-05-13) diff --git a/hutool-cache/src/main/java/cn/hutool/cache/impl/AbstractCache.java b/hutool-cache/src/main/java/cn/hutool/cache/impl/AbstractCache.java index 3703478f0..5ff371789 100755 --- a/hutool-cache/src/main/java/cn/hutool/cache/impl/AbstractCache.java +++ b/hutool-cache/src/main/java/cn/hutool/cache/impl/AbstractCache.java @@ -88,12 +88,10 @@ public abstract class AbstractCache implements Cache { final MutableObj mKey = MutableObj.of(key); // issue#3618 对于替换的键值对,不做满队列检查和清除 - if (cacheMap.containsKey(mKey)) { - CacheObj oldObj = cacheMap.get(mKey); - if (oldObj != null) { - onRemove(oldObj.key, oldObj.obj); - cacheMap.remove(mKey); - } + final CacheObj oldObj = cacheMap.get(mKey); + if (null != oldObj) { + onRemove(oldObj.key, oldObj.obj); + // 存在相同key,覆盖之 cacheMap.put(mKey, co); } else { if (isFull()) { diff --git a/hutool-cache/src/test/java/cn/hutool/cache/CacheTest.java b/hutool-cache/src/test/java/cn/hutool/cache/CacheTest.java index d7202e0a5..ed862b9be 100755 --- a/hutool-cache/src/test/java/cn/hutool/cache/CacheTest.java +++ b/hutool-cache/src/test/java/cn/hutool/cache/CacheTest.java @@ -4,13 +4,13 @@ import cn.hutool.cache.impl.TimedCache; import cn.hutool.core.date.DateUnit; import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.RandomUtil; - -import static org.junit.jupiter.api.Assertions.*; - +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.util.concurrent.atomic.AtomicInteger; +import static org.junit.jupiter.api.Assertions.*; + /** * 缓存测试用例 * @@ -155,19 +155,15 @@ public class CacheTest { */ @Test public void reentrantCache_clear_Method_Test() { - Cache lruCache = CacheUtil.newLRUCache(4); - lruCache.setListener(new CacheListener() { - @Override - public void onRemove(String key, String cachedObject) { - System.out.println(" listener key= "+ key+" value = "+cachedObject.toString()+" cachedObject资源释放操作..."); - } - } ); + final AtomicInteger removeCount = new AtomicInteger(); + final Cache lruCache = CacheUtil.newLRUCache(4); + lruCache.setListener((key, cachedObject) -> removeCount.getAndIncrement()); lruCache.put("key1","String1"); lruCache.put("key2","String2"); lruCache.put("key3","String3"); lruCache.put("key1","String4");//key已经存在,原始putWithoutLock方法存在资源泄露 lruCache.put("key4","String5"); lruCache.clear();//ReentrantCache类clear()方法存在资源泄露 - + Assertions.assertEquals(5, removeCount.get()); } }