Index: MetaClassRegistry.java =================================================================== RCS file: /home/projects/groovy/scm/groovy/groovy-core/src/main/groovy/lang/MetaClassRegistry.java,v retrieving revision 1.26 diff -u -r1.26 MetaClassRegistry.java --- MetaClassRegistry.java 21 Oct 2005 09:03:03 -0000 1.26 +++ MetaClassRegistry.java 28 Dec 2005 13:07:16 -0000 @@ -46,6 +46,7 @@ package groovy.lang; import java.beans.IntrospectionException; +import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.security.AccessController; @@ -89,7 +90,13 @@ private static MetaClassRegistry instanceInclude; private static MetaClassRegistry instanceExclude; - + /* + * Flag indicating that the registry is initializing itself. If true, the registered + * meta classes will be stored using strong references. This allows to hold strong + * references to core classes that should be always available. + */ + private boolean initializing = true; + public MetaClassRegistry() { this(LOAD_DEFAULT, true); } @@ -117,6 +124,30 @@ registerMethods(DefaultGroovyStaticMethods.class, false); checkInitialised(); } + + initializing = false; + } + + private MetaClass getWeakMetaClass(Class theClass) { + Object obj = metaClasses.get(theClass); + MetaClass metaClass = null; + + if(obj != null) { + if(obj instanceof WeakReference) { + metaClass = (MetaClass) ((WeakReference) obj).get(); + } else { + metaClass = (MetaClass) obj; + } + } + + return metaClass; + } + + private void putWeakMetaClass(Class theClass, MetaClass metaClass) { + if(initializing) + metaClasses.put(theClass, metaClass); // strong ref + else + metaClasses.put(theClass, new WeakReference(metaClass)); } private void registerMethods(final Class theClass, final boolean instanceMethods) { @@ -139,11 +170,11 @@ public MetaClass getMetaClass(Class theClass) { synchronized (theClass) { - MetaClass answer = (MetaClass) metaClasses.get(theClass); + MetaClass answer = getWeakMetaClass(theClass); if (answer == null) { answer = getMetaClassFor(theClass); answer.checkInitialised(); - metaClasses.put(theClass, answer); + putWeakMetaClass(theClass, answer); } return answer; } @@ -161,7 +192,7 @@ * @param theMetaClass */ public void setMetaClass(Class theClass, MetaClass theMetaClass) { - metaClasses.put(theClass, theMetaClass); + putWeakMetaClass(theClass, theMetaClass); } public boolean useAccessible() { @@ -201,7 +232,12 @@ } synchronized (loaderMap) { - GroovyClassLoader groovyLoader = (GroovyClassLoader) loaderMap.get(loader); + WeakReference ref = (WeakReference) loaderMap.get(loader); + GroovyClassLoader groovyLoader = null; + + if(ref != null) + groovyLoader = (GroovyClassLoader) ref.get(); + if (groovyLoader == null) { if (loader == null || loader == getClass().getClassLoader()) { groovyLoader = this.loader; @@ -227,7 +263,7 @@ }); } } - loaderMap.put(loader, groovyLoader); + loaderMap.put(loader, new WeakReference(groovyLoader)); } return groovyLoader; @@ -242,8 +278,16 @@ // to avoid concurrent modification exception List list = new ArrayList(metaClasses.values()); for (Iterator iter = list.iterator(); iter.hasNext();) { - MetaClass metaClass = (MetaClass) iter.next(); - metaClass.checkInitialised(); + Object obj = iter.next(); + MetaClass metaClass = null; + if(obj instanceof WeakReference) { + metaClass = (MetaClass) ((WeakReference) obj).get(); + } else { + metaClass = (MetaClass) obj; + } + + if(metaClass != null) + metaClass.checkInitialised(); } } @@ -251,10 +295,10 @@ * Used by MetaClass when registering new methods which avoids initializing the MetaClass instances on lookup */ MetaClass lookup(Class theClass) { - MetaClass answer = (MetaClass) metaClasses.get(theClass); + MetaClass answer = getWeakMetaClass(theClass); if (answer == null) { answer = getMetaClassFor(theClass); - metaClasses.put(theClass, answer); + putWeakMetaClass(theClass, answer); } return answer; }