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