User: mnf999 Date: 02/01/20 07:20:39 Modified: src/main/org/jboss/system ServiceLibraries.java Log: Unified ClassLoaders Revision Changes Path 1.13 +201 -194 jboss/src/main/org/jboss/system/ServiceLibraries.java Index: ServiceLibraries.java =================================================================== RCS file: /cvsroot/jboss/jboss/src/main/org/jboss/system/ServiceLibraries.java,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- ServiceLibraries.java 2002/01/04 00:15:07 1.12 +++ ServiceLibraries.java 2002/01/20 15:20:33 1.13 @@ -1,10 +1,9 @@ /* - * JBoss, the OpenSource J2EE webOS - * - * Distributable under LGPL license. - * See terms of license at gnu.org. - */ - +* JBoss, the OpenSource J2EE webOS +* +* Distributable under LGPL license. +* See terms of license at gnu.org. +*/ package org.jboss.system; import java.net.URL; @@ -18,203 +17,212 @@ import javax.management.MBeanRegistration; import javax.management.MBeanServer; import javax.management.ObjectName; + -import org.jboss.system.URLClassLoader; +//import org.jboss.logging.log4j.JBossCategory; -/** - * Service Libraries. The service libraries is a central repository of all - * classes loaded by the ClassLoaders - * - * @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a> - * @author <a href="mailto:[EMAIL PROTECTED]">Ole Husgaard</a> - * @version $Revision: 1.12 $ <p> - * - * <b>20010830 marc fleury:</b> - * <ul> - * <li>initial import - * </ul> - * - * <b>20010908 david jencks:</b> - * <ul> - * <li>Modified to make undeploy work better. - * </ul> - * - * <b>20011003 Ole Husgaard:</b> - * <ul> - * <li>Changed synchronization to avoid deadlock with SUNs - * java.lang.Classloader implementation. Kudos to Dr. Christoph Jung - * and Sacha Labourey for identifying this problem. - * </ul> - */ +/** +* Service Libraries. The service libraries is a central repository of all +* classes loaded by the ClassLoaders +* +* @see <related> +* @author <a href="mailto:[EMAIL PROTECTED]">Marc Fleury</a> +* @author <a href="mailto:[EMAIL PROTECTED]">Ole Husgaard</a> +* @version $Revision: 1.13 $ <p> +* +* <b>20010830 marc fleury:</b> +* <ul>initial import +* <li> +* </ul> +* <b>20010908 david jencks:</b> +* <ul>Modified to make undeploy work better. +* <li> +* <b>20011003 Ole Husgaard:</b> +* <ul>Changed synchronization to avoid deadlock with SUNs +* java.lang.Classloader implementation. Kudos to Dr. Christoph Jung +* and Sacha Labourey for identifying this problem. +* <li> +* </ul> +* +*/ public class ServiceLibraries - implements ServiceLibrariesMBean, MBeanRegistration +implements ServiceLibrariesMBean, MBeanRegistration { /** The bootstrap interface to the log4j system */ - private static BootstrapLogger log = - BootstrapLogger.getLogger(ServiceLibraries.class); + private static BootstrapLogger log = BootstrapLogger.getLogger(ServiceLibraries.class); + + // Static -------------------------------------------------------- private static ServiceLibraries libraries; - + + // Constants ----------------------------------------------------- + + // Attributes ---------------------------------------------------- + + /** - * The classloaders we use for loading classes here. - */ + * The classloaders we use for loading classes here. + */ private Set classLoaders; - - /** - * Maps class names of the classes loaded here to the classes. - */ + + /* + * Maps class names of the classes loaded here to the classes. + */ private Map classes; - - /** - * Maps class loaders to the set of classes they loaded here. - */ + + /* + * Maps class loaders to the set of classes they loaded here. + */ private Map clToClassSetMap; - + /** - * The version number of the {@link #clToClassSetMap} map. - * If a lookup of a class detects a change in this while calling - * the classloaders with locks removed, the {@link #clToClassSetMap} - * and {@link #classes} fields should <em>only</em> be modified - * if the classloader used for loading the class is still in the - * {@link #classLoaders} set. - */ + * The version number of the {@link #clToClassSetMap} map. + * If a lookup of a class detects a change in this while calling + * the classloaders with locks removed, the {@link #clToClassSetMap} + * and {@link #classes} fields should <em>only</em> be modified + * if the classloader used for loading the class is still in the + * {@link #classLoaders} set. + */ private long clToClassSetMapVersion = 0; - - /** - * Maps resource names of resources looked up here to the URLs used to - * load them. - */ + + /* + * Maps resource names of resources looked up here to the URLs used to + * load them. + */ private Map resources; - - /** - * Maps class loaders to the set of resource names they looked up here. - */ + + /* + * Maps class loaders to the set of resource names they looked up here. + */ private Map clToResourceSetMap; - + /** - * The version number of the {@link #clToResourceSetMap} map. - * If a lookup of a resource detects a change in this while - * calling the classloaders with locks removed, the - * {@link #clToResourceSetMap} and {@link #resources} fields should - * <em>only</em> be modified if the classloader used for loading - * the class is still in the {@link #classLoaders} set. - */ + * The version number of the {@link #clToResourceSetMap} map. + * If a lookup of a resource detects a change in this while + * calling the classloaders with locks removed, the + * {@link #clToResourceSetMap} and {@link #resources} fields should + * <em>only</em> be modified if the classloader used for loading + * the class is still in the {@link #classLoaders} set. + */ private long clToResourceSetMapVersion = 0; - - /** - * Gets the Libraries attribute of the ServiceLibraries class - * - * @return The Libraries value - */ + + // Constructors -------------------------------------------------- + + // Public -------------------------------------------------------- + + /** + * Gets the Libraries attribute of the ServiceLibraries class + * + * @return The Libraries value + */ public static ServiceLibraries getLibraries() { if (libraries == null) libraries = new ServiceLibraries(); - + return libraries; } - + // ServiceClassLoaderMBean implementation ------------------------ - + /** - * Gets the Name attribute of the ServiceLibraries object. - * - * @return The Name value - */ + * Gets the Name attribute of the ServiceLibraries object. + * + * @return The Name value + */ public String getName() { return "ServiceLibraries"; } /** - * Find a resource in the ServiceLibraries object. - * - * @param name The name of the resource - * @param scl The asking class loader - * @return An URL for reading the resource, or <code>null</code> if the - * resource could not be found. - */ + * Find a resource in the ServiceLibraries object. + * + * @param name The name of the resource + * @param scl The asking class loader + * @return An URL for reading the resource, or <code>null</code> if the + * resource could not be found. + */ public URL getResource(String name, ClassLoader scl) { Set classLoaders2; long clToResourceSetMapVersion2; - + + URL resource = null; + + // First ask for the class to the asking class loader + if (scl instanceof UnifiedClassLoader) + resource = ((UnifiedClassLoader)scl).getResourceLocally(name); + + if (resource != null) return resource; + synchronized (this) { // Is it in the global map? if (resources.containsKey(name)) return (URL)resources.get(name); - + // No, make copies of the classLoader reference to avoid working on // a later version of it. classLoaders2 = classLoaders; - + // Save the current version of the resource map, so we // can detect if it has changed. clToResourceSetMapVersion2 = clToResourceSetMapVersion; } - - URL resource = null; - - // First ask for the class to the asking class loader - if (scl instanceof URLClassLoader) - resource = ((URLClassLoader)scl).getResourceLocally(name); - - if (resource == null) + + // If not start asking around to URL classloaders for it + for (Iterator iter = classLoaders2.iterator(); iter.hasNext();) { - // If not start asking around to URL classloaders for it - for (Iterator iter = classLoaders2.iterator(); iter.hasNext();) - { - URLClassLoader cl = (URLClassLoader)iter.next(); - - if (!cl.equals(scl)) - { // already tried this one - resource = cl.getResourceLocally(name); - - if (resource != null) + UnifiedClassLoader cl = (UnifiedClassLoader)iter.next(); + + if (!cl.equals(scl)) + { // already tried this one + resource = cl.getResourceLocally(name); + + if (resource != null) + { + synchronized (this) { - synchronized (this) + // Did the version change? + if (clToResourceSetMapVersion2 != clToResourceSetMapVersion) { - // Did the version change? - if (clToResourceSetMapVersion2 != clToResourceSetMapVersion) - { - // Yes. Is the class loader we used still here? - if (!classLoaders.contains(cl)) - { - // No, it was removed from under us. - // Don't change the maps, simply return the resource. - return resource; - } - } - // We can keep track - resources.put(name, resource); - - // When we cycle the cl we also need to remove the classes it loaded - Set set = (Set)clToResourceSetMap.get(cl); - if (set == null) + // Yes. Is the class loader we used still here? + if (!classLoaders.contains(cl)) { - set = new HashSet(); - clToResourceSetMap.put(cl, set); + // No, it was removed from under us. + // Don't change the maps, simply return the resource. + return resource; } - - set.add(name); - - return resource; } - } // if we found it - } - } // for all ClassLoaders - } // If we reach here, all of the classloaders currently in the VM don't know about the resource - + // We can keep track + resources.put(name, resource); + + // When we cycle the cl we also need to remove the classes it loaded + Set set = (Set)clToResourceSetMap.get(cl); + if (set == null) + { + set = new HashSet(); + clToResourceSetMap.put(cl, set); + } + + set.add(name); + + return resource; + } + } // if we found it + } + } // for all ClassLoaders, If we reach here, all of the classloaders currently in the VM don't know about the resource + return resource; } /** - * Add a ClassLoader to the ServiceLibraries object. - * - * @param cl The class loader to be added. - */ - public synchronized void addClassLoader(URLClassLoader cl) + * Add a ClassLoader to the ServiceLibraries object. + * + * @param cl The class loader to be added. + */ + public synchronized void addClassLoader(UnifiedClassLoader cl) { // we allow for duplicate class loader definitions in the services.xml files // we should however only keep the first classloader declared @@ -223,46 +231,46 @@ { // We create a new copy of the classLoaders set. classLoaders = new HashSet(classLoaders); - + classLoaders.add(cl); if( trace ) { - log.trace("Libraries adding URLClassLoader " + cl.hashCode() + - " key URL " + cl.getKeyURL().toString()); + log.trace("Libraries adding UnifiedClassLoader " + cl.hashCode() + + " key URL " + cl.getURL().toString()); } } else if( trace ) { - log.trace("Libraries skipping duplicate URLClassLoader for key URL " + - cl.getKeyURL().toString()); + log.trace("Libraries skipping duplicate UnifiedClassLoader for key URL " + + cl.getURL().toString()); } } - + /** - * Remove a ClassLoader from the ServiceLibraries object. - * - * @param cl The ClassLoader to be removed. - */ - public synchronized void removeClassLoader(URLClassLoader cl) + * Remove a ClassLoader from the ServiceLibraries object. + * + * @param cl The ClassLoader to be removed. + */ + public synchronized void removeClassLoader(UnifiedClassLoader cl) { boolean trace = log.isTraceEnabled(); if( trace ) log.trace("removing classloader " + cl); - + if (!classLoaders.contains(cl)) return; // nothing to remove - + // We create a new copy of the classLoaders set. classLoaders = new HashSet(classLoaders); classLoaders.remove(cl); - + if (clToClassSetMap.containsKey(cl)) { // We have a new version of the map ++clToClassSetMapVersion; - + Set clClasses = (Set)clToClassSetMap.remove(cl); - + for (Iterator iter = clClasses.iterator(); iter.hasNext();) { Object o = iter.next(); @@ -276,9 +284,9 @@ if (clToResourceSetMap.containsKey(cl)) { ++clToResourceSetMapVersion; - + Set clResources = (Set)clToResourceSetMap.remove(cl); - + for (Iterator iter = clResources.iterator(); iter.hasNext();) { Object o = iter.next(); @@ -290,64 +298,64 @@ } /** - * Load a class in the ServiceLibraries object. - * - * @param name The name of the class - * @param resolve If <code>true</code>, the class will be resolved - * @param scl The asking class loader - * @return The loaded class. - * resource could not be found. - * @throws ClassNotFoundException If the class could not be found. - */ + * Load a class in the ServiceLibraries object. + * + * @param name The name of the class + * @param resolve If <code>true</code>, the class will be resolved + * @param scl The asking class loader + * @return The loaded class. + * resource could not be found. + * @throws ClassNotFoundException If the class could not be found. + */ public Class loadClass(String name, boolean resolve, ClassLoader scl) - throws ClassNotFoundException + throws ClassNotFoundException { Class foundClass; Set classLoaders2; long clToClassSetMapVersion2; - + synchronized (this) { // Try the local map already foundClass = (Class)classes.get(name); - + if (foundClass != null) return foundClass; - + // Not found, make copies of the classLoader reference to avoid // working on a later version of it. classLoaders2 = classLoaders; - + // Save the current version of the class map, so we // can detect if it has changed. clToClassSetMapVersion2 = clToClassSetMapVersion; } - + // If not start asking around to URL classloaders for it // who will find it? - URLClassLoader cl = null; - - if (scl instanceof URLClassLoader) + UnifiedClassLoader cl = null; + + if (scl instanceof UnifiedClassLoader) { // First ask the asking classloader chances are the dependent class is in there try { - foundClass = ((URLClassLoader)scl).loadClassLocally(name, resolve); - + foundClass = ((UnifiedClassLoader)scl).loadClassLocally(name, resolve); + //If we get here we know the scl is the right one - cl = (URLClassLoader)scl; + cl = (UnifiedClassLoader)scl; } catch (ClassNotFoundException ignored) { } } - + Iterator allLoaders = classLoaders2.iterator(); while (allLoaders.hasNext() && (foundClass == null)) { // next! - cl = (URLClassLoader)allLoaders.next(); - + cl = (UnifiedClassLoader)allLoaders.next(); + if (!scl.equals(cl)) { try @@ -360,7 +368,7 @@ } } } //allLoaders - + if (foundClass != null) { synchronized (this) @@ -378,7 +386,7 @@ } // We can keep track classes.put(name, foundClass); - + // When we cycle the cl we also need to remove the classes it loaded Set set = (Set)clToClassSetMap.get(cl); if (set == null) @@ -388,12 +396,12 @@ } set.add(name); } - + return foundClass; } + + // If we reach here, all of the classloaders currently in the VM don't know about the class - // If we reach here, all of the classloaders currently in the VM don't - // know about the class throw new ClassNotFoundException(name); } @@ -408,7 +416,6 @@ public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception { - // this.server = server; classLoaders = new HashSet(); classes = new HashMap();
_______________________________________________ Jboss-development mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/jboss-development
