You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xmlbeans.apache.org by ce...@apache.org on 2005/05/09 23:24:04 UTC

svn commit: r169362 - in /xmlbeans/branches/1.x/src: typeimpl/org/apache/xmlbeans/impl/schema/ typeimpl/org/apache/xmlbeans/impl/values/ xmlpublic/org/apache/xmlbeans/ xmlstore/org/apache/xmlbeans/impl/store/

Author: cezar
Date: Mon May  9 14:24:02 2005
New Revision: 169362

URL: http://svn.apache.org/viewcvs?rev=169362&view=rev
Log:
Contributed by Dimitry Gerasimenko. Fix permgen memory bug, if XMLBeans is used in a classloader other than the system classloader (like in a servlet container), after there are no user refences to XMLBeans, the garbage collector can unload XMLBeans classes...Pratial port from v2, fix for JIRA bug XMLBEANS-148

Modified:
    xmlbeans/branches/1.x/src/typeimpl/org/apache/xmlbeans/impl/schema/SchemaTypeLoaderImpl.java
    xmlbeans/branches/1.x/src/typeimpl/org/apache/xmlbeans/impl/schema/StscState.java
    xmlbeans/branches/1.x/src/typeimpl/org/apache/xmlbeans/impl/values/NamespaceContext.java
    xmlbeans/branches/1.x/src/xmlpublic/org/apache/xmlbeans/XmlBeans.java
    xmlbeans/branches/1.x/src/xmlpublic/org/apache/xmlbeans/XmlFactoryHook.java
    xmlbeans/branches/1.x/src/xmlstore/org/apache/xmlbeans/impl/store/CursorData.java
    xmlbeans/branches/1.x/src/xmlstore/org/apache/xmlbeans/impl/store/Root.java
    xmlbeans/branches/1.x/src/xmlstore/org/apache/xmlbeans/impl/store/Saver.java

Modified: xmlbeans/branches/1.x/src/typeimpl/org/apache/xmlbeans/impl/schema/SchemaTypeLoaderImpl.java
URL: http://svn.apache.org/viewcvs/xmlbeans/branches/1.x/src/typeimpl/org/apache/xmlbeans/impl/schema/SchemaTypeLoaderImpl.java?rev=169362&r1=169361&r2=169362&view=diff
==============================================================================
--- xmlbeans/branches/1.x/src/typeimpl/org/apache/xmlbeans/impl/schema/SchemaTypeLoaderImpl.java (original)
+++ xmlbeans/branches/1.x/src/typeimpl/org/apache/xmlbeans/impl/schema/SchemaTypeLoaderImpl.java Mon May  9 14:24:02 2005
@@ -36,6 +36,8 @@
 import java.util.List;
 import java.util.IdentityHashMap;
 
+import java.lang.ref.SoftReference;
+
 public class SchemaTypeLoaderImpl extends SchemaTypeLoaderBase
 {
     private ResourceLoader _resourceLoader;
@@ -53,29 +55,50 @@
     private Map _documentCache;
     private Map _classnameCache;
 
-    private static SchemaTypeLoaderImpl buildContextTypeLoader()
+    // The following maintains a cache of SchemaTypeLoaders per ClassLoader per Thread.
+    // I use soft references to allow the garbage collector to reclain the type loaders
+    // and/pr class loaders at will.
+
+    private static ThreadLocal _cachedTypeSystems =
+        new ThreadLocal() { protected Object initialValue() { return new ArrayList(); } };
+
+    public static SchemaTypeLoaderImpl getContextTypeLoader ( )
     {
-        return new SchemaTypeLoaderImpl(new SchemaTypeLoader[] { BuiltinSchemaTypeSystem.get() } , null, Thread.currentThread().getContextClassLoader());
-    }
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
 
-    private static ThreadLocal _threadTypeSystems =
-        new ThreadLocal()
+        ArrayList a = (ArrayList) _cachedTypeSystems.get();
+
+        int candidate = -1;
+        SchemaTypeLoaderImpl result = null;
+
+        for ( int i = 0 ; i < a.size() ; i++ )
         {
-            protected Object initialValue() { return new WeakHashMap(); }
-        };
+            SchemaTypeLoaderImpl tl = (SchemaTypeLoaderImpl) ((SoftReference) a.get( i )).get();
 
-    public static SchemaTypeLoaderImpl getContextTypeLoader()
-    {
-        WeakHashMap candidates = (WeakHashMap) _threadTypeSystems.get();
-        ClassLoader threadContextClassLoader = Thread.currentThread().getContextClassLoader();
-        SchemaTypeLoaderImpl candidate = (SchemaTypeLoaderImpl) candidates.get( threadContextClassLoader );
+            if (tl == null)
+                a.remove( i-- );
+            else if (tl._classLoader == cl)
+            {
+                candidate = i;
+                result = tl;
+            }
+        }
 
-        if (candidate == null)
+        if (candidate == -1)
         {
-            candidate = buildContextTypeLoader();
-            candidates.put( threadContextClassLoader, candidate );
+            result =  new SchemaTypeLoaderImpl( new SchemaTypeLoader[] { BuiltinSchemaTypeSystem.get() } , null, cl );
+            a.add( new SoftReference( result ) );
+            candidate = a.size() - 1;
         }
-        return candidate;
+
+        if (candidate > 0)
+        {
+            Object t = a.get( 0 );
+            a.set( 0, a.get( candidate ) );
+            a.set( candidate, t );
+        }
+
+        return result;
     }
     
     public static SchemaTypeLoader build(SchemaTypeLoader[] searchPath, ResourceLoader resourceLoader, ClassLoader classLoader)

Modified: xmlbeans/branches/1.x/src/typeimpl/org/apache/xmlbeans/impl/schema/StscState.java
URL: http://svn.apache.org/viewcvs/xmlbeans/branches/1.x/src/typeimpl/org/apache/xmlbeans/impl/schema/StscState.java?rev=169362&r1=169361&r2=169362&view=diff
==============================================================================
--- xmlbeans/branches/1.x/src/typeimpl/org/apache/xmlbeans/impl/schema/StscState.java (original)
+++ xmlbeans/branches/1.x/src/typeimpl/org/apache/xmlbeans/impl/schema/StscState.java Mon May  9 14:24:02 2005
@@ -45,6 +45,7 @@
 import org.w3.x2001.xmlSchema.SchemaDocument;
 import org.xml.sax.EntityResolver;
 
+
 /**
  * This class represents the state of the SchemaTypeSystemCompiler as it's
  * going.
@@ -790,24 +791,32 @@
         }
     }
 
-    private static ThreadLocal stscStack = new ThreadLocal()
-    {
-        protected Object initialValue() { return new StscStack(); }
-    };
+    private static ThreadLocal tl_stscStack = new ThreadLocal();
 
     public static StscState start()
     {
-        return ((StscStack)stscStack.get()).push();
+        StscStack stscStack = (StscStack) tl_stscStack.get();
+
+        if (stscStack==null)
+        {
+            stscStack = new StscStack();
+            tl_stscStack.set(stscStack);
+        }
+        return stscStack.push();
     }
 
     public static StscState get()
     {
-        return ((StscStack)stscStack.get()).current;
+        return ((StscStack) tl_stscStack.get()).current;
     }
 
     public static void end()
     {
-        ((StscStack)stscStack.get()).pop();
+        StscStack stscStack = (StscStack) tl_stscStack.get();
+        stscStack.pop();
+        if (stscStack.stack.size()==0)
+            tl_stscStack.set(null);            // this is required to release all the references in this classloader
+                                               // which will enable class unloading and avoid OOM in PermGen
     }
 
     private final static XmlValueRef XMLSTR_PRESERVE = buildString("preserve");

Modified: xmlbeans/branches/1.x/src/typeimpl/org/apache/xmlbeans/impl/values/NamespaceContext.java
URL: http://svn.apache.org/viewcvs/xmlbeans/branches/1.x/src/typeimpl/org/apache/xmlbeans/impl/values/NamespaceContext.java?rev=169362&r1=169361&r2=169362&view=diff
==============================================================================
--- xmlbeans/branches/1.x/src/typeimpl/org/apache/xmlbeans/impl/values/NamespaceContext.java (original)
+++ xmlbeans/branches/1.x/src/typeimpl/org/apache/xmlbeans/impl/values/NamespaceContext.java Mon May  9 14:24:02 2005
@@ -26,6 +26,8 @@
 
 import org.apache.xmlbeans.xml.stream.StartElement;
 
+import java.lang.ref.SoftReference;
+
 public class NamespaceContext implements PrefixResolver
 {
     private static final int TYPE_STORE    = 1;
@@ -87,14 +89,27 @@
         }
     }
 
-    private static ThreadLocal NamespaceContextStack = new ThreadLocal()
+    private static ThreadLocal tl_namespaceContextStack = new ThreadLocal()
     {
-        protected Object initialValue() { return new NamespaceContextStack(); }
+        protected Object initialValue() { return new SoftReference(new NamespaceContextStack()); }
     };
 
+    private static NamespaceContextStack getNamespaceContextStack()
+    {
+        SoftReference softRef = (SoftReference)tl_namespaceContextStack.get();
+        NamespaceContextStack namespaceContextStack = (NamespaceContextStack) (softRef).get();
+        if (namespaceContextStack==null)
+        {
+            namespaceContextStack = new NamespaceContextStack();
+            tl_namespaceContextStack.set(new SoftReference(namespaceContextStack));
+        }
+        return namespaceContextStack;
+    }
+
+
     public static void push(NamespaceContext next)
     {
-        ((NamespaceContextStack)NamespaceContextStack.get()).push(next);
+        getNamespaceContextStack().push(next);
     }
             
     public String getNamespaceForPrefix(String prefix)
@@ -144,12 +159,12 @@
 
     public static PrefixResolver getCurrent()
     {
-        return ((NamespaceContextStack)NamespaceContextStack.get()).current;
+        return getNamespaceContextStack().current;
     }
     
     public static void pop()
     {
-        ((NamespaceContextStack)NamespaceContextStack.get()).pop();
+        getNamespaceContextStack().pop();
     }
 
 }

Modified: xmlbeans/branches/1.x/src/xmlpublic/org/apache/xmlbeans/XmlBeans.java
URL: http://svn.apache.org/viewcvs/xmlbeans/branches/1.x/src/xmlpublic/org/apache/xmlbeans/XmlBeans.java?rev=169362&r1=169361&r2=169362&view=diff
==============================================================================
--- xmlbeans/branches/1.x/src/xmlpublic/org/apache/xmlbeans/XmlBeans.java (original)
+++ xmlbeans/branches/1.x/src/xmlpublic/org/apache/xmlbeans/XmlBeans.java Mon May  9 14:24:02 2005
@@ -19,6 +19,8 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.lang.ref.SoftReference;
+
 
 /**
  * Provides an assortment of utilities
@@ -80,7 +82,7 @@
         {
             protected Object initialValue()
             {
-                return new QNameCache( 32 );
+                return new SoftReference(new QNameCache( 32 ));
             }
         };
 
@@ -89,7 +91,14 @@
      */
     public static QNameCache getQNameCache ( )
     {
-        return (QNameCache) _threadLocalLoaderQNameCache.get();
+        SoftReference softRef = (SoftReference)_threadLocalLoaderQNameCache.get();
+        QNameCache qnameCache = (QNameCache) (softRef).get();
+        if (qnameCache==null)
+        {
+            qnameCache = new QNameCache( 32 );
+            _threadLocalLoaderQNameCache.set(new SoftReference(qnameCache));
+        }
+        return qnameCache;
     }
 
     /**

Modified: xmlbeans/branches/1.x/src/xmlpublic/org/apache/xmlbeans/XmlFactoryHook.java
URL: http://svn.apache.org/viewcvs/xmlbeans/branches/1.x/src/xmlpublic/org/apache/xmlbeans/XmlFactoryHook.java?rev=169362&r1=169361&r2=169362&view=diff
==============================================================================
--- xmlbeans/branches/1.x/src/xmlpublic/org/apache/xmlbeans/XmlFactoryHook.java (original)
+++ xmlbeans/branches/1.x/src/xmlpublic/org/apache/xmlbeans/XmlFactoryHook.java Mon May  9 14:24:02 2005
@@ -23,6 +23,7 @@
 
 import org.apache.xmlbeans.xml.stream.XMLInputStream;
 import org.apache.xmlbeans.xml.stream.XMLStreamException;
+import java.lang.ref.SoftReference;
 
 /**
  * A hook for the XML Bean Factory mechanism.
@@ -87,7 +88,8 @@
          */ 
         public static XmlFactoryHook getHook()
         {
-            return (XmlFactoryHook)threadHook.get();
+            SoftReference softRef = (SoftReference)threadHook.get();
+            return softRef==null ? null : (XmlFactoryHook)softRef.get();
         }
 
         /**
@@ -95,7 +97,7 @@
          */ 
         public static void setHook(XmlFactoryHook hook)
         {
-            threadHook.set(hook);
+            threadHook.set(new SoftReference(hook));
         }
 
         // provided to prevent unwanted construction

Modified: xmlbeans/branches/1.x/src/xmlstore/org/apache/xmlbeans/impl/store/CursorData.java
URL: http://svn.apache.org/viewcvs/xmlbeans/branches/1.x/src/xmlstore/org/apache/xmlbeans/impl/store/CursorData.java?rev=169362&r1=169361&r2=169362&view=diff
==============================================================================
--- xmlbeans/branches/1.x/src/xmlstore/org/apache/xmlbeans/impl/store/CursorData.java (original)
+++ xmlbeans/branches/1.x/src/xmlstore/org/apache/xmlbeans/impl/store/CursorData.java Mon May  9 14:24:02 2005
@@ -18,6 +18,7 @@
 import org.apache.xmlbeans.impl.store.Splay.CursorGoober;
 
 import java.util.ArrayList;
+import java.lang.ref.SoftReference;
 
 public final class CursorData
 {
@@ -27,14 +28,22 @@
 
         CursorData cd;
 
-        if (dataCache.size() == 0)
-            cd = new CursorData( r );
-        else
+        SoftReference softRef;
+        while (dataCache.size() != 0)
         {
-            cd = (CursorData) dataCache.remove( dataCache.size() - 1 );
-            cd._goober.set( r );
+            softRef = (SoftReference)(dataCache.remove(dataCache.size()-1));
+            cd = (CursorData)softRef.get();
+            if (cd==null)
+                continue;
+            else
+            {
+                cd._goober.set( r );
+                return cd;
+            }
         }
-        
+
+        cd = new CursorData( r );
+
         return cd;
     }
 
@@ -43,9 +52,12 @@
         _goober = new CursorGoober( r );
     }
 
+
+
+
     private static ThreadLocal tl_CachedCursorData =
         new ThreadLocal() { protected Object initialValue() { return new ArrayList(); } };
-    
+
     protected void release ( boolean cache )
     {
         if (_goober.getSplay() != null)
@@ -62,7 +74,7 @@
                 ArrayList dataCache = (ArrayList) tl_CachedCursorData.get();
 
                 if (dataCache.size() < 128)
-                    dataCache.add( this );
+                    dataCache.add( new SoftReference (this) );
             }
         }
     }

Modified: xmlbeans/branches/1.x/src/xmlstore/org/apache/xmlbeans/impl/store/Root.java
URL: http://svn.apache.org/viewcvs/xmlbeans/branches/1.x/src/xmlstore/org/apache/xmlbeans/impl/store/Root.java?rev=169362&r1=169361&r2=169362&view=diff
==============================================================================
--- xmlbeans/branches/1.x/src/xmlstore/org/apache/xmlbeans/impl/store/Root.java (original)
+++ xmlbeans/branches/1.x/src/xmlstore/org/apache/xmlbeans/impl/store/Root.java Mon May  9 14:24:02 2005
@@ -16,6 +16,7 @@
 package org.apache.xmlbeans.impl.store;
 
 import java.lang.reflect.Method;
+import java.lang.ref.SoftReference;
 
 import org.apache.xmlbeans.impl.common.EncodingMap;
 import org.apache.xmlbeans.impl.common.QNameHelper;
@@ -583,21 +584,34 @@
         {
             protected Object initialValue()
             {
-                SaxLoader sl = PiccoloSaxLoader.newInstance();
+                return new SoftReference(createSaxLoader());
+            }
+        };
 
-                if (sl == null)
-                    sl = DefaultSaxLoader.newInstance();
+    private static SaxLoader createSaxLoader ()
+    {
+        SaxLoader sl = PiccoloSaxLoader.newInstance();
 
-                if (sl == null)
-                    throw new RuntimeException( "Can't find an XML parser" );
+        if (sl == null)
+            sl = DefaultSaxLoader.newInstance();
 
-                return sl;
-            }
-        };
+        if (sl == null)
+            throw new RuntimeException( "Can't find an XML parser" );
+
+        return sl;
+    }
 
     private static SaxLoader getSaxLoader ( )
     {
-        return (SaxLoader) tl_SaxLoaders.get();
+        SoftReference softRef = (SoftReference)tl_SaxLoaders.get();
+        SaxLoader saxLoader = (SaxLoader) softRef.get();
+        if (saxLoader==null)
+        {
+            saxLoader = createSaxLoader();
+            tl_SaxLoaders.set(new SoftReference(saxLoader));
+        }
+        return saxLoader;
+
     }
     
 

Modified: xmlbeans/branches/1.x/src/xmlstore/org/apache/xmlbeans/impl/store/Saver.java
URL: http://svn.apache.org/viewcvs/xmlbeans/branches/1.x/src/xmlstore/org/apache/xmlbeans/impl/store/Saver.java?rev=169362&r1=169361&r2=169362&view=diff
==============================================================================
--- xmlbeans/branches/1.x/src/xmlstore/org/apache/xmlbeans/impl/store/Saver.java (original)
+++ xmlbeans/branches/1.x/src/xmlstore/org/apache/xmlbeans/impl/store/Saver.java Mon May  9 14:24:02 2005
@@ -41,6 +41,7 @@
 import java.util.Iterator;
 import java.util.Map;
 import java.util.ConcurrentModificationException;
+import java.lang.ref.SoftReference;
 import javax.xml.namespace.QName;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.DocumentBuilder;
@@ -4426,17 +4427,34 @@
         {
             protected Object initialValue()
             {
-                try
-                {
-                    return DocumentBuilderFactory.newInstance().newDocumentBuilder();
-                }
-                catch ( ParserConfigurationException e )
-                {
-                    throw new RuntimeException( e.getMessage(), e );
-                }
+                return new SoftReference(createDocumentBuilder());
             }
         };
-    
+
+    public static DocumentBuilder createDocumentBuilder()
+    {
+        try
+        {
+            return DocumentBuilderFactory.newInstance().newDocumentBuilder();
+        }
+        catch ( ParserConfigurationException e )
+        {
+            throw new RuntimeException( e.getMessage(), e );
+        }
+    }
+
+    public static DocumentBuilder getThreadLocalDocumentBuilder() {
+
+        SoftReference softRef = (SoftReference)_threadDocumentBuilderFactory.get();
+        DocumentBuilder documentBuilder = (DocumentBuilder) softRef.get();
+        if (documentBuilder==null)
+        {
+            documentBuilder = createDocumentBuilder();
+            _threadDocumentBuilderFactory.set(new SoftReference(documentBuilder));
+        }
+        return documentBuilder;
+    }
+
     static final class DomSaver extends Saver
     {
         DomSaver ( Root r, Splay s, int p, boolean createDoc, XmlOptions options )
@@ -4451,7 +4469,7 @@
             // TODO - add an options which specifies a Document with which
             // to create the fragment
 
-            _doc = ((DocumentBuilder) _threadDocumentBuilderFactory.get()).newDocument();
+            _doc = getThreadLocalDocumentBuilder().newDocument();
 
             Node result;
 



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xmlbeans.apache.org
For additional commands, e-mail: commits-help@xmlbeans.apache.org