修复ReentrantCache的clear存在的外部资源泄露问题

This commit is contained in:
yanzhongxin 2025-06-06 15:05:55 +08:00
parent 7739f8b015
commit 5931264706
2 changed files with 33 additions and 1 deletions

View File

@ -1,8 +1,11 @@
package cn.hutool.cache.impl;
import cn.hutool.core.collection.CopiedIter;
import cn.hutool.core.lang.mutable.Mutable;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
/**
@ -81,7 +84,14 @@ public abstract class ReentrantCache<K, V> extends AbstractCache<K, V> {
public void clear() {
lock.lock();
try {
cacheMap.clear();
// 获取所有键的副本
Set<Mutable<K>> keys = new HashSet<>(cacheMap.keySet());
for (Mutable<K> key : keys) {
CacheObj<K, V> co = removeWithoutLock(key.get());
if (co != null) {
onRemove(co.key, co.obj); // 触发资源释放
}
}
} finally {
lock.unlock();
}

View File

@ -148,4 +148,26 @@ public class CacheTest {
assertFalse(ALARM_CACHE.containsKey(1));
assertEquals(1, counter.get());
}
/**
* ReentrantCache类clear()方法AbstractCache.putWithoutLock方法可能导致资源泄露
* https://github.com/chinabugotech/hutool/issues/3957
*/
@Test
public void reentrantCache_clear_Method_Test() {
Cache<String, String> lruCache = CacheUtil.newLRUCache(4);
lruCache.setListener(new CacheListener<String, String>() {
@Override
public void onRemove(String key, String cachedObject) {
System.out.println(" listener key= "+ key+" value = "+cachedObject.toString()+" cachedObject资源释放操作...");
}
} );
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()方法存在资源泄露
}
}