Skip to content

Commit 51b17a7

Browse files
committed
[bugfix] Ensure that the collection cache used by NewArrayNodeSet can be released if there is memory pressure
1 parent 6cd5844 commit 51b17a7

File tree

1 file changed

+26
-10
lines changed

1 file changed

+26
-10
lines changed

exist-core/src/main/java/org/exist/dom/persistent/NewArrayNodeSet.java

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,12 @@
6565
import org.w3c.dom.Node;
6666

6767
import javax.annotation.Nullable;
68-
import java.util.*;
68+
import java.lang.ref.WeakReference;
69+
import java.util.Arrays;
70+
import java.util.HashSet;
71+
import java.util.Iterator;
72+
import java.util.NoSuchElementException;
73+
import java.util.Set;
6974

7075
/**
7176
* A fast node set implementation, based on arrays to store nodes and documents.
@@ -91,7 +96,7 @@
9196
*/
9297
public class NewArrayNodeSet extends AbstractArrayNodeSet implements ExtNodeSet, DocumentSet {
9398

94-
private Set<Collection> cachedCollections = null;
99+
@Nullable private WeakReference<Set<Collection>> cachedCollectionsRef = null;
95100

96101
private int documentCount = 0;
97102

@@ -1038,16 +1043,27 @@ public boolean equalDocs(final DocumentSet other) {
10381043

10391044
@Override
10401045
public Iterator<Collection> getCollectionIterator() {
1041-
sort();
1042-
if(cachedCollections == null) {
1043-
cachedCollections = new HashSet<>();
1044-
for(int i = 0; i < documentCount; i++) {
1045-
final DocumentImpl doc = nodes[documentNodesOffset[i]].getOwnerDocument();
1046-
if(!cachedCollections.contains(doc.getCollection())) {
1047-
cachedCollections.add(doc.getCollection());
1048-
}
1046+
// First, try and retrieve from Cache
1047+
Set<Collection> cachedCollections;
1048+
if (this.cachedCollectionsRef != null) {
1049+
cachedCollections = this.cachedCollectionsRef.get();
1050+
if (cachedCollections != null) {
1051+
return cachedCollections.iterator();
10491052
}
10501053
}
1054+
1055+
sort();
1056+
1057+
// Second, Cache is empty, so create a Cache and return
1058+
cachedCollections = new HashSet<>();
1059+
for (int i = 0; i < documentCount; i++) {
1060+
final DocumentImpl doc = nodes[documentNodesOffset[i]].getOwnerDocument();
1061+
final Collection collection = doc.getCollection();
1062+
cachedCollections.add(collection);
1063+
}
1064+
1065+
this.cachedCollectionsRef = new WeakReference<>(cachedCollections);
1066+
10511067
return cachedCollections.iterator();
10521068
}
10531069

0 commit comments

Comments
 (0)