mirror of
https://gitee.com/dromara/hutool.git
synced 2025-06-28 04:35:14 +08:00
Merge pull request #3958 from IcoreE/yanzhongxin-v5-dev
AbstractCache.putWithoutLock方法可能导致的外部资源泄露问题
This commit is contained in:
commit
a60c70ca86
@ -89,7 +89,11 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
||||
|
||||
// issue#3618 对于替换的键值对,不做满队列检查和清除
|
||||
if (cacheMap.containsKey(mKey)) {
|
||||
// 存在相同key,覆盖之
|
||||
CacheObj<K, V> oldObj = cacheMap.get(mKey);
|
||||
if (oldObj != null) {
|
||||
onRemove(oldObj.key, oldObj.obj);
|
||||
cacheMap.remove(mKey);
|
||||
}
|
||||
cacheMap.put(mKey, co);
|
||||
} else {
|
||||
if (isFull()) {
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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()方法存在资源泄露
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user