User: sparre  
  Date: 01/10/03 14:43:29

  Modified:    src/main/org/jboss/system ServiceLibraries.java
  Log:
  Fixed a possible race between classloader removal and class load.
  
  Revision  Changes    Path
  1.6       +62 -25    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.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- ServiceLibraries.java     2001/10/03 18:47:10     1.5
  +++ ServiceLibraries.java     2001/10/03 21:43:29     1.6
  @@ -29,7 +29,7 @@
    * @see <related>
    * @author <a href="mailto:[EMAIL PROTECTED]";>Marc Fleury</a>
    * @author <a href="mailto:[EMAIL PROTECTED]";>Ole Husgaard</a>
  - * @version $Revision: 1.5 $ <p>
  + * @version $Revision: 1.6 $ <p>
    *
    *      <b>20010830 marc fleury:</b>
    *      <ul>initial import
  @@ -77,6 +77,16 @@
       */
      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.
  +    */
  +   private long clToClassSetMapVersion = 0;
  +
      /*
       *  Maps resource names of resources looked up here to the URLs used to
       *  load them.
  @@ -88,6 +98,16 @@
       */
      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.
  +    */
  +   private long clToResourceSetMapVersion = 0;
  +
      // Constructors --------------------------------------------------
   
      // Public --------------------------------------------------------
  @@ -129,19 +149,20 @@
      public URL getResource(String name, ClassLoader scl)
      {
         Set classLoaders2;
  -      Map resources2;
  -      Map clToResourceSetMap2;
  +      long clToResourceSetMapVersion2;
   
         synchronized (this) {
            // Is it in the global map?
            if (resources.containsKey(name))
               return (URL)resources.get(name);
   
  -         // No, make copies of the references to avoid working on or changing
  -         // a later version of these.
  +         // No, make copies of the classLoader reference to avoid working on
  +         // a later version of it.
            classLoaders2 = classLoaders;
  -         resources2 = resources;
  -         clToResourceSetMap2 = clToResourceSetMap;
  +
  +         // Save the current version of the resource map, so we
  +         // can detect if it has changed.
  +         clToResourceSetMapVersion2 = clToResourceSetMapVersion;
         }
   
         URL resource = null;
  @@ -161,17 +182,25 @@
   
                  if (resource != null) {
                     synchronized (this) {
  +                     // 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
  -                     resources2.put(name, resource);
  +                     resources.put(name, resource);
   
                        // When we cycle the cl we also need to remove the classes it 
loaded
  -                     Set set = (Set)clToResourceSetMap2.get(cl);
  +                     Set set = (Set)clToResourceSetMap.get(cl);
                        if (set == null) {
                           set = new HashSet();
  -                        clToResourceSetMap2.put(cl, set);
  +                        clToResourceSetMap.put(cl, set);
                        }
   
  -                     //set.add(resource);
                        set.add(name);
   
                        return resource;
  @@ -223,8 +252,8 @@
         classLoaders.remove(cl);
   
         if (clToClassSetMap.containsKey(cl)) {
  -         // Create a new copy of the map
  -         clToClassSetMap = new HashMap(clToClassSetMap);
  +         // We have a new version of the map
  +         ++clToClassSetMapVersion;
   
            Set clClasses = (Set)clToClassSetMap.remove(cl);
   
  @@ -237,7 +266,7 @@
         
         // Same procedure for resources
         if (clToResourceSetMap.containsKey(cl)) {
  -         clToResourceSetMap = new HashMap(clToResourceSetMap);
  +         ++clToResourceSetMapVersion;
   
            Set clResources = (Set)clToResourceSetMap.remove(cl);
   
  @@ -265,8 +294,7 @@
      {
         Class foundClass;
         Set classLoaders2;
  -      Map classes2;
  -      Map clToClassSetMap2;
  +      long clToClassSetMapVersion2;
   
         synchronized (this) {
            // Try the local map already
  @@ -275,11 +303,13 @@
            if (foundClass != null)
               return foundClass;
   
  -         // Not found, make copies of the references to avoid working on
  -         // or changing a later version of these.
  +         // Not found, make copies of the classLoader reference to avoid
  +         // working on a later version of it.
            classLoaders2 = classLoaders;
  -         classes2 = classes;
  -         clToClassSetMap2 = clToClassSetMap;
  +
  +         // 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
  @@ -314,17 +344,24 @@
   
         if (foundClass != null) {
            synchronized (this) {
  +            // Did the version change?
  +            if (clToClassSetMapVersion2 != clToClassSetMapVersion) {
  +               // 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 class.
  +                  return foundClass;
  +               }
  +            }
               // We can keep track
  -            classes2.put(name, foundClass);
  +            classes.put(name, foundClass);
   
               // When we cycle the cl we also need to remove the classes it loaded
  -            Set set = (Set)clToClassSetMap2.get(cl);
  +            Set set = (Set)clToClassSetMap.get(cl);
               if (set == null) {
                  set = new HashSet();
  -               clToClassSetMap2.put(cl, set);
  +               clToClassSetMap.put(cl, set);
               }
  -
  -            //set.add(foundClass);
               set.add(name);
            }
   
  
  
  

_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/jboss-development

Reply via email to