[jboss-cvs] JBossAS SVN: r93150 - in projects/jboss-cl/branches/Branch_2_0/classloader/src: main/java/org/jboss/classloader/spi/base and 3 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Thu Sep 3 04:13:58 EDT 2009


Author: wolfc
Date: 2009-09-03 04:13:57 -0400 (Thu, 03 Sep 2009)
New Revision: 93150

Added:
   projects/jboss-cl/branches/Branch_2_0/classloader/src/test/java/org/jboss/test/classloader/jbcl114/
   projects/jboss-cl/branches/Branch_2_0/classloader/src/test/java/org/jboss/test/classloader/jbcl114/BlockingClassLoaderDomain.java
   projects/jboss-cl/branches/Branch_2_0/classloader/src/test/java/org/jboss/test/classloader/jbcl114/BlockingClassLoaderSystem.java
   projects/jboss-cl/branches/Branch_2_0/classloader/src/test/java/org/jboss/test/classloader/jbcl114/test/
   projects/jboss-cl/branches/Branch_2_0/classloader/src/test/java/org/jboss/test/classloader/jbcl114/test/CachingClassesUnitTestCase.java
Modified:
   projects/jboss-cl/branches/Branch_2_0/classloader/src/main/java/org/jboss/classloader/spi/ClassLoaderSystem.java
   projects/jboss-cl/branches/Branch_2_0/classloader/src/main/java/org/jboss/classloader/spi/base/BaseClassLoader.java
Log:
JBCL-114: unit test and fix for the losers of the race to BaseClassLoader.loadClass synchronized block

Modified: projects/jboss-cl/branches/Branch_2_0/classloader/src/main/java/org/jboss/classloader/spi/ClassLoaderSystem.java
===================================================================
--- projects/jboss-cl/branches/Branch_2_0/classloader/src/main/java/org/jboss/classloader/spi/ClassLoaderSystem.java	2009-09-03 06:38:46 UTC (rev 93149)
+++ projects/jboss-cl/branches/Branch_2_0/classloader/src/main/java/org/jboss/classloader/spi/ClassLoaderSystem.java	2009-09-03 08:13:57 UTC (rev 93150)
@@ -23,6 +23,7 @@
 
 import java.security.ProtectionDomain;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
@@ -30,7 +31,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.Collections;
 
 import javax.management.MBeanRegistration;
 import javax.management.MBeanServer;
@@ -182,6 +182,7 @@
    public ClassLoaderDomain createAndRegisterDomain(String name, ParentPolicy parentPolicy, Loader parent)
    {
       ClassLoaderDomain result = createDomain(name);
+      assert result != null : "createDomain(" + name + ") returned null";
       result.setParentPolicy(parentPolicy);
       result.setParent(parent);
       registerDomain(result);

Modified: projects/jboss-cl/branches/Branch_2_0/classloader/src/main/java/org/jboss/classloader/spi/base/BaseClassLoader.java
===================================================================
--- projects/jboss-cl/branches/Branch_2_0/classloader/src/main/java/org/jboss/classloader/spi/base/BaseClassLoader.java	2009-09-03 06:38:46 UTC (rev 93149)
+++ projects/jboss-cl/branches/Branch_2_0/classloader/src/main/java/org/jboss/classloader/spi/base/BaseClassLoader.java	2009-09-03 08:13:57 UTC (rev 93150)
@@ -436,6 +436,9 @@
 
       synchronized (this)
       {
+         // JBCL-114: did we lose the race to the synchronized?
+         result = isLoadedClass(name, trace);
+         
          // Not already loaded use the domain
          if (result == null)
             result = loadClassFromDomain(name, trace);

Added: projects/jboss-cl/branches/Branch_2_0/classloader/src/test/java/org/jboss/test/classloader/jbcl114/BlockingClassLoaderDomain.java
===================================================================
--- projects/jboss-cl/branches/Branch_2_0/classloader/src/test/java/org/jboss/test/classloader/jbcl114/BlockingClassLoaderDomain.java	                        (rev 0)
+++ projects/jboss-cl/branches/Branch_2_0/classloader/src/test/java/org/jboss/test/classloader/jbcl114/BlockingClassLoaderDomain.java	2009-09-03 08:13:57 UTC (rev 93150)
@@ -0,0 +1,79 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.test.classloader.jbcl114;
+
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.jboss.classloader.spi.ClassLoaderDomain;
+import org.jboss.classloader.spi.base.BaseClassLoader;
+
+/**
+ * @author <a href="mailto:cdewolf at redhat.com">Carlo de Wolf</a>
+ * @version $Revision: $
+ */
+public class BlockingClassLoaderDomain extends ClassLoaderDomain
+{
+   private boolean block = true;
+   private ReentrantLock lock = new ReentrantLock();
+   
+   protected BlockingClassLoaderDomain(String name)
+   {
+      super(name);
+   }
+   
+   @Override
+   protected Class<?> loadClass(BaseClassLoader classLoader, String name, boolean allExports) throws ClassNotFoundException
+   {
+      try
+      {
+         waitForIt();
+      }
+      catch(InterruptedException e)
+      {
+         throw new ClassNotFoundException("interrupted", e);
+      }
+      // there can be only 1
+      boolean locked = lock.tryLock();
+      if(!locked)
+         throw new IllegalStateException("only one thread is allowed to use this class loader domain");
+      return super.loadClass(classLoader, name, allExports);
+   }
+   
+   public void unblock()
+   {
+      synchronized (this)
+      {
+         block = false;
+         notifyAll();
+      }
+   }
+   
+   private void waitForIt() throws InterruptedException
+   {
+      if(!block) return;
+      synchronized (this)
+      {
+         while(block)
+            wait();
+      }
+   }
+}

Added: projects/jboss-cl/branches/Branch_2_0/classloader/src/test/java/org/jboss/test/classloader/jbcl114/BlockingClassLoaderSystem.java
===================================================================
--- projects/jboss-cl/branches/Branch_2_0/classloader/src/test/java/org/jboss/test/classloader/jbcl114/BlockingClassLoaderSystem.java	                        (rev 0)
+++ projects/jboss-cl/branches/Branch_2_0/classloader/src/test/java/org/jboss/test/classloader/jbcl114/BlockingClassLoaderSystem.java	2009-09-03 08:13:57 UTC (rev 93150)
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.test.classloader.jbcl114;
+
+import org.jboss.classloader.spi.ClassLoaderDomain;
+import org.jboss.classloader.spi.ClassLoaderSystem;
+
+/**
+ * @author <a href="mailto:cdewolf at redhat.com">Carlo de Wolf</a>
+ * @version $Revision: $
+ */
+public class BlockingClassLoaderSystem extends ClassLoaderSystem
+{
+   @Override
+   protected ClassLoaderDomain createDomain(String name)
+   {
+      return new BlockingClassLoaderDomain(name);
+   }
+}

Added: projects/jboss-cl/branches/Branch_2_0/classloader/src/test/java/org/jboss/test/classloader/jbcl114/test/CachingClassesUnitTestCase.java
===================================================================
--- projects/jboss-cl/branches/Branch_2_0/classloader/src/test/java/org/jboss/test/classloader/jbcl114/test/CachingClassesUnitTestCase.java	                        (rev 0)
+++ projects/jboss-cl/branches/Branch_2_0/classloader/src/test/java/org/jboss/test/classloader/jbcl114/test/CachingClassesUnitTestCase.java	2009-09-03 08:13:57 UTC (rev 93150)
@@ -0,0 +1,95 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.test.classloader.jbcl114.test;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.jboss.classloader.spi.ClassLoaderDomain;
+import org.jboss.classloader.spi.ClassLoaderSystem;
+import org.jboss.classloader.spi.ParentPolicy;
+import org.jboss.classloader.spi.filter.ClassFilter;
+import org.jboss.classloader.test.support.MockClassLoaderPolicy;
+import org.jboss.test.classloader.AbstractClassLoaderTest;
+import org.jboss.test.classloader.domain.support.NoMatchClassFilter;
+import org.jboss.test.classloader.jbcl114.BlockingClassLoaderDomain;
+import org.jboss.test.classloader.jbcl114.BlockingClassLoaderSystem;
+
+/**
+ * Race the synchronized block in BaseClassLoader.loadClass.
+ * 
+ * @author <a href="mailto:cdewolf at redhat.com">Carlo de Wolf</a>
+ * @version $Revision: $
+ */
+public class CachingClassesUnitTestCase extends AbstractClassLoaderTest
+{
+   public CachingClassesUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   protected ClassLoaderSystem createBlockingClassLoaderSystem()
+   {
+      return new BlockingClassLoaderSystem();
+   }
+   
+   /**
+    * The second thread allowed into the synchronized block of BaseClassLoader.loadClass
+    * must not touch the ClassLoaderDomain.
+    */
+   public void testCache() throws Exception
+   {
+      ClassLoaderSystem system = createBlockingClassLoaderSystem();
+      NoMatchClassFilter filter = new NoMatchClassFilter(ClassLoaderDomain.class);
+      ParentPolicy parentPolicy = new ParentPolicy(ClassFilter.JAVA_ONLY, filter);
+      BlockingClassLoaderDomain domain = (BlockingClassLoaderDomain) system.createAndRegisterDomain("test", parentPolicy, null);
+      
+      MockClassLoaderPolicy policy = createMockClassLoaderPolicy();
+      policy.setPathsAndPackageNames(ClassLoaderDomain.class);
+      final ClassLoader classLoader = system.registerClassLoaderPolicy(domain, policy);
+      
+      int numThreads = 2;
+      ExecutorService executor = Executors.newFixedThreadPool(numThreads);
+      Future<?>[] results = new Future[numThreads];
+      for(int i = 0; i < results.length; i++)
+      {
+         results[i] = executor.submit(new Callable<Void>() {
+            public Void call() throws Exception
+            {
+               assertLoadClass(ClassLoaderDomain.class, classLoader);
+               return null;
+            }
+         });
+      }
+      executor.shutdown();
+      domain.unblock();
+      executor.awaitTermination(5, TimeUnit.SECONDS);
+      // no exceptions means a job well done
+      for(int i = 0; i < results.length; i++)
+      {
+         results[i].get(1, TimeUnit.SECONDS);
+      }
+   }
+}




More information about the jboss-cvs-commits mailing list