Author: mrglavas
Date: Sun Dec 13 23:45:22 2009
New Revision: 890145
URL: http://svn.apache.org/viewvc?rev=890145&view=rev
Log:
JIRA Issue #1299: https://issues.apache.org/jira/browse/XERCESJ-1299. Use weak
references for storing the NodeIterators so that they can be garbage collected
if the application no longer has any references to them. Inspired by the patch
by Ludger Bünger except that I used a LinkedList instead of a WeakHashMap due
its good memory management when items are removed (and also good for bulk
removals through its iterator).
Modified:
xerces/java/trunk/src/org/apache/xerces/dom/DocumentImpl.java
Modified: xerces/java/trunk/src/org/apache/xerces/dom/DocumentImpl.java
URL:
http://svn.apache.org/viewvc/xerces/java/trunk/src/org/apache/xerces/dom/DocumentImpl.java?rev=890145&r1=890144&r2=890145&view=diff
==============================================================================
--- xerces/java/trunk/src/org/apache/xerces/dom/DocumentImpl.java (original)
+++ xerces/java/trunk/src/org/apache/xerces/dom/DocumentImpl.java Sun Dec 13
23:45:22 2009
@@ -18,8 +18,14 @@
package org.apache.xerces.dom;
import java.io.Serializable;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Vector;
import org.apache.xerces.dom.events.EventImpl;
@@ -94,9 +100,11 @@
// Data
//
- /** Iterators */
- // REVISIT: Should this be transient? -Ac
- protected Vector iterators;
+ /** Node Iterators */
+ protected transient List iterators;
+
+ /** Reference queue for cleared Node Iterator references */
+ protected transient ReferenceQueue iteratorReferenceQueue;
/** Ranges */
// REVISIT: Should this be transient? -Ac
@@ -227,10 +235,12 @@
filter,
entityReferenceExpansion);
if (iterators == null) {
- iterators = new Vector();
+ iterators = new LinkedList();
+ iteratorReferenceQueue = new ReferenceQueue();
}
- iterators.addElement(iterator);
+ removeStaleIteratorReferences();
+ iterators.add(new WeakReference(iterator, iteratorReferenceQueue));
return iterator;
}
@@ -276,18 +286,55 @@
// Not DOM Level 2. Support DocumentTraversal methods.
//
- /** This is not called by the developer client. The
- * developer client uses the detach() function on the
- * NodeIterator itself. <p>
+ /**
+ * This is not called by the developer client. The
+ * developer client uses the detach() function on the
+ * NodeIterator itself. <p>
*
- * This function is called from the NodeIterator#detach().
+ * This function is called from the NodeIterator#detach().
*/
- void removeNodeIterator(NodeIterator nodeIterator) {
+ void removeNodeIterator(NodeIterator nodeIterator) {
if (nodeIterator == null) return;
if (iterators == null) return;
- iterators.removeElement(nodeIterator);
+ removeStaleIteratorReferences();
+ Iterator i = iterators.iterator();
+ while (i.hasNext()) {
+ Object iterator = ((Reference) i.next()).get();
+ if (iterator == nodeIterator) {
+ i.remove();
+ return;
+ }
+ // Remove stale reference from the list.
+ else if (iterator == null) {
+ i.remove();
+ }
+ }
+ }
+
+ /**
+ * Remove stale iterator references from the iterator list.
+ */
+ void removeStaleIteratorReferences() {
+ Reference ref = iteratorReferenceQueue.poll();
+ int count = 0;
+ while (ref != null) {
+ ++count;
+ ref = iteratorReferenceQueue.poll();
+ }
+ if (count > 0) {
+ Iterator i = iterators.iterator();
+ while (i.hasNext()) {
+ Object iterator = ((Reference) i.next()).get();
+ if (iterator == null) {
+ i.remove();
+ if (--count <= 0) {
+ return;
+ }
+ }
+ }
+ }
}
//
@@ -1177,9 +1224,17 @@
}
private void notifyIteratorsRemovingNode(NodeImpl oldChild) {
- final int size = iterators.size();
- for (int i = 0; i != size; i++) {
- ((NodeIteratorImpl)iterators.elementAt(i)).removeNode(oldChild);
+ removeStaleIteratorReferences();
+ final Iterator i = iterators.iterator();
+ while (i.hasNext()) {
+ NodeIteratorImpl iterator = (NodeIteratorImpl) ((Reference)
i.next()).get();
+ if (iterator != null) {
+ iterator.removeNode(oldChild);
+ }
+ // Remove stale reference from the list.
+ else {
+ i.remove();
+ }
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]