#101103: Prevent document leak by not reusing DOM parsers. reset() is flawed aand there's no reliable way around it. Test included for the brave that would like the cache back. Root_model_refactoring core-ext-sep_root editor_hints_cleanup_83347b_root issue_110566_root merge_trunk_to_unstable_uml_visualcomponent_july_16_2007
authorpnejedly@netbeans.org
Mon, 02 Jul 2007 15:01:07 +0000
changeset 287d6e135d48b83
parent 286 144937d35a3c
child 288 15a10984300a
#101103: Prevent document leak by not reusing DOM parsers. reset() is flawed aand there's no reliable way around it. Test included for the brave that would like the cache back.
openide.util/src/org/openide/xml/XMLUtil.java
openide.util/test/unit/src/org/openide/xml/XMLUtilTest.java
     1.1 --- a/openide.util/src/org/openide/xml/XMLUtil.java	Mon Jun 25 19:12:18 2007 +0000
     1.2 +++ b/openide.util/src/org/openide/xml/XMLUtil.java	Mon Jul 02 15:01:07 2007 +0000
     1.3 @@ -13,7 +13,7 @@
     1.4   * "Portions Copyrighted [year] [name of copyright owner]"
     1.5   *
     1.6   * The Original Software is NetBeans. The Initial Developer of the Original
     1.7 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
     1.8 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
     1.9   * Microsystems, Inc. All Rights Reserved.
    1.10   */
    1.11  
    1.12 @@ -262,17 +262,6 @@
    1.13      }
    1.14  
    1.15      /**
    1.16 -     * Cache of DocumentBuilder instances per thread.
    1.17 -     * They are relatively expensive to create, so don't do it more than necessary.
    1.18 -     */
    1.19 -    @SuppressWarnings("unchecked")
    1.20 -    private static final ThreadLocal<DocumentBuilder>[] builderTL = new ThreadLocal[4];
    1.21 -    static {
    1.22 -        for (int i = 0; i < 4; i++) {
    1.23 -            builderTL[i] = new ThreadLocal<DocumentBuilder>();
    1.24 -        }
    1.25 -    }
    1.26 -    /**
    1.27       * Create from factory a DocumentBuilder and let it create a org.w3c.dom.Document.
    1.28       * This method takes InputSource. After successful finish the document tree is returned.
    1.29       *
    1.30 @@ -293,19 +282,15 @@
    1.31          EntityResolver entityResolver
    1.32      ) throws IOException, SAXException {
    1.33          
    1.34 -        int index = (validate ? 0 : 1) + (namespaceAware ? 0 : 2);
    1.35 -        DocumentBuilder builder = builderTL[index].get();
    1.36 -        if (builder == null) {
    1.37 -            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    1.38 -            factory.setValidating(validate);
    1.39 -            factory.setNamespaceAware(namespaceAware);
    1.40 +        DocumentBuilder builder = null;
    1.41 +        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    1.42 +        factory.setValidating(validate);
    1.43 +        factory.setNamespaceAware(namespaceAware);
    1.44  
    1.45 -            try {
    1.46 -                builder = factory.newDocumentBuilder();
    1.47 -            } catch (ParserConfigurationException ex) {
    1.48 -                throw new SAXException("Cannot create parser satisfying configuration parameters", ex); //NOI18N
    1.49 -            }
    1.50 -            builderTL[index].set(builder);
    1.51 +        try {
    1.52 +            builder = factory.newDocumentBuilder();
    1.53 +        } catch (ParserConfigurationException ex) {
    1.54 +            throw new SAXException("Cannot create parser satisfying configuration parameters", ex); //NOI18N
    1.55          }
    1.56          
    1.57          if (errorHandler != null) {
    1.58 @@ -657,18 +642,16 @@
    1.59       * @see "#62006"
    1.60       */
    1.61      private static Document normalize(Document orig) throws IOException {
    1.62 -        DocumentBuilder builder = builderTL[0].get();
    1.63 -        if (builder == null) {
    1.64 -            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    1.65 -            factory.setValidating(false);
    1.66 -            factory.setNamespaceAware(false);
    1.67 -            try {
    1.68 -                builder = factory.newDocumentBuilder();
    1.69 -            } catch (ParserConfigurationException e) {
    1.70 -                throw (IOException) new IOException("Cannot create parser satisfying configuration parameters: " + e).initCause(e); //NOI18N
    1.71 -            }
    1.72 -            builderTL[0].set(builder);
    1.73 +        DocumentBuilder builder = null;
    1.74 +        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    1.75 +        factory.setValidating(false);
    1.76 +        factory.setNamespaceAware(false);
    1.77 +        try {
    1.78 +            builder = factory.newDocumentBuilder();
    1.79 +        } catch (ParserConfigurationException e) {
    1.80 +            throw (IOException) new IOException("Cannot create parser satisfying configuration parameters: " + e).initCause(e); //NOI18N
    1.81          }
    1.82 +
    1.83          DocumentType doctype = null;
    1.84          NodeList nl = orig.getChildNodes();
    1.85          for (int i = 0; i < nl.getLength(); i++) {
     2.1 --- a/openide.util/test/unit/src/org/openide/xml/XMLUtilTest.java	Mon Jun 25 19:12:18 2007 +0000
     2.2 +++ b/openide.util/test/unit/src/org/openide/xml/XMLUtilTest.java	Mon Jul 02 15:01:07 2007 +0000
     2.3 @@ -13,7 +13,7 @@
     2.4   * "Portions Copyrighted [year] [name of copyright owner]"
     2.5   *
     2.6   * The Original Software is NetBeans. The Initial Developer of the Original
     2.7 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
     2.8 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
     2.9   * Microsystems, Inc. All Rights Reserved.
    2.10   */
    2.11  
    2.12 @@ -24,6 +24,7 @@
    2.13  import java.io.CharConversionException;
    2.14  import java.io.IOException;
    2.15  import java.io.StringReader;
    2.16 +import java.lang.ref.WeakReference;
    2.17  import java.net.URL;
    2.18  import java.net.URLClassLoader;
    2.19  import javax.xml.parsers.DocumentBuilderFactory;
    2.20 @@ -347,4 +348,14 @@
    2.21          String data2 = baos.toString().replaceAll("\r\n", "\n");
    2.22          assertEquals("identity replacement should not mess up significant whitespace", data, data2);
    2.23      }
    2.24 +    
    2.25 +    public void testDocumentLeak() throws Exception {
    2.26 +        String data = "<foo xmlns='bar'><baz/></foo>";
    2.27 +        Document doc = XMLUtil.parse(new InputSource(new StringReader(data)), false, true, null, null);
    2.28 +
    2.29 +        WeakReference<Document> wr = new WeakReference<Document>(doc);
    2.30 +        doc = null;
    2.31 +        
    2.32 +        assertGC("Document should be freed", wr);
    2.33 +    }
    2.34  }