mrglavas 2003/11/18 13:47:35 Modified: java/src/org/apache/xerces/impl XMLEntityManager.java Log: Fixing Bugs #897 & #19152. They're very different reports, but they're both symptoms of the same bug. We were keeping a list of all the readers opened during a parse and only closing them after we finish. This means if a document contains millions of internal entity references we'll have a list of millions of references to StringReader that cannot be garbage collected until we dump the list after the parse, and since we don't close the streams until we're done, the operating system may run out of file handles. Solution: Once we've parsed an entity, close the reader and then remove it from the list. If parsing halts for some reason, cleanup the remaining readers as we already do. http://nagoya.apache.org/bugzilla/show_bug.cgi?id=897 http://nagoya.apache.org/bugzilla/show_bug.cgi?id=19152 Revision Changes Path 1.69 +26 -15 xml-xerces/java/src/org/apache/xerces/impl/XMLEntityManager.java Index: XMLEntityManager.java =================================================================== RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/XMLEntityManager.java,v retrieving revision 1.68 retrieving revision 1.69 diff -u -r1.68 -r1.69 --- XMLEntityManager.java 7 Nov 2003 00:26:17 -0000 1.68 +++ XMLEntityManager.java 18 Nov 2003 21:47:35 -0000 1.69 @@ -1078,9 +1078,9 @@ //reader = new OneCharReader(reader); } - // we've seen a new Reader. put it in a list, so that - // we can close it later. - fOwnReaders.addElement(reader); + // We've seen a new Reader. + // Push it on the stack so we can close it later. + fReaderStack.push(reader); // push entity on stack if (fCurrentEntity != null) { @@ -1129,23 +1129,21 @@ return fEntityScanner; } // getEntityScanner():XMLEntityScanner - // a list of Readers ever seen - protected Vector fOwnReaders = new Vector(); + // A stack containing all the open readers + protected Stack fReaderStack = new Stack(); /** * Close all opened InputStreams and Readers opened by this parser. */ public void closeReaders() { // close all readers - for (int i = fOwnReaders.size()-1; i >= 0; i--) { + for (int i = fReaderStack.size()-1; i >= 0; i--) { try { - ((Reader)fOwnReaders.elementAt(i)).close(); + ((Reader)fReaderStack.pop()).close(); } catch (IOException e) { // ignore } } - // and clear the list - fOwnReaders.removeAllElements(); } // @@ -1710,12 +1708,25 @@ if (fEntityHandler != null) { fEntityHandler.endEntity(fCurrentEntity.name); } + + // Close the reader for the current entity once we're + // done with it, and remove it from our stack. If parsing + // is halted at some point, the rest of the readers on + // the stack will be closed during cleanup. + try { + fCurrentEntity.reader.close(); + } + catch (IOException e) { + // ignore + } + // REVISIT: We should never encounter underflow if the calls + // to startEntity and endEntity are balanced, but guard + // against the EmptyStackException for now. -- mrglavas + if(!fReaderStack.isEmpty()) { + fReaderStack.pop(); + } - // pop stack - // REVISIT: we are done with the current entity, should close - // the associated reader - //fCurrentEntity.reader.close(); - // Now we close all readers after we finish parsing + // Pop entity stack. fCurrentEntity = fEntityStack.size() > 0 ? (ScannedEntity)fEntityStack.pop() : null; fEntityScanner.setCurrentEntity(fCurrentEntity);
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]