提交 2b4c81e6 编写于 作者: P Phillip Webb

Fix memory leak in ConcurrentReferenceHashMap

Update ConcurrentReferenceHashMap to protect against references that
have been garbage collected but for some reason do not appear as a
`pollForPurge` result.

Also added purgeUnreferencedEntries() method to allow for programmatic
cleanup.

Issue: SPR-11440
上级 fe6a9826
......@@ -338,6 +338,19 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
}
}
/**
* Remove any entries that have been garbage collected and are no longer referenced.
* Under normal circumstances garbage collected entries are automatically purged as
* items are added or removed from the Map. This method can be used to force a purge,
* and is useful when the Map is read frequently but updated less often.
*/
public void purgeUnreferencedEntries() {
for (Segment segment : this.segments) {
segment.restructureIfNecessary(false);
}
}
@Override
public int size() {
int size = 0;
......@@ -512,7 +525,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
* references that have been garbage collected.
* @param allowResize if resizing is permitted
*/
private void restructureIfNecessary(boolean allowResize) {
protected final void restructureIfNecessary(boolean allowResize) {
boolean needsResize = ((this.count > 0) && (this.count >= this.resizeThreshold));
Reference<K, V> reference = this.referenceManager.pollForPurge();
if ((reference != null) || (needsResize && allowResize)) {
......@@ -550,7 +563,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
restructured[i] = null;
}
while (reference != null) {
if (!toPurge.contains(reference)) {
if (!toPurge.contains(reference) && (reference.get() != null)) {
int index = getIndex(reference.getHash(), restructured);
restructured[index] = this.referenceManager.createReference(
reference.get(), reference.getHash(),
......@@ -564,7 +577,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
if (resizing) {
setReferences(restructured);
}
this.count = countAfterRestructure;
this.count = Math.max(countAfterRestructure, 0);
} finally {
unlock();
}
......@@ -974,6 +987,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
enqueue();
clear();
}
}
......@@ -1007,6 +1021,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
enqueue();
clear();
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册