You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by va...@apache.org on 2007/01/30 15:17:37 UTC

svn commit: r501401 - in /harmony/enhanced: classlib/trunk/modules/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassLoaderTest.java drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/ClassLoader.java

Author: varlax
Date: Tue Jan 30 06:17:35 2007
New Revision: 501401

URL: http://svn.apache.org/viewvc?view=rev&rev=501401
Log:
Fixed: 
HARMONY-1939 [drlvm][classlib] loadClass method in ClassLoader is not synchronized
HARMONY-2736 [drlvm][kernel] j.l.ClassLoader.definePackage() is not thread-safe
Tested on SUSE10@ia32

Modified:
    harmony/enhanced/classlib/trunk/modules/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassLoaderTest.java
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/ClassLoader.java

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassLoaderTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassLoaderTest.java?view=diff&rev=501401&r1=501400&r2=501401
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassLoaderTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassLoaderTest.java Tue Jan 30 06:17:35 2007
@@ -53,6 +53,106 @@
             Policy.setPolicy(back);
         }
     }
+    
+    static class SyncTestClassLoader extends ClassLoader {
+        Object lock;
+        volatile int numFindClassCalled;
+        
+        SyncTestClassLoader(Object o) {
+            this.lock = o;
+            numFindClassCalled = 0;
+        }
+
+        /*
+         * Byte array of bytecode equivalent to the following source code:
+         * public class TestClass {
+         * }
+         */
+        private byte[] classData = new byte[] {
+            -54, -2, -70, -66, 0, 0, 0, 49, 0, 13,
+            10, 0, 3, 0, 10, 7, 0, 11, 7, 0,
+            12, 1, 0, 6, 60, 105, 110, 105, 116, 62,
+            1, 0, 3, 40, 41, 86, 1, 0, 4, 67,
+            111, 100, 101, 1, 0, 15, 76, 105, 110, 101,
+            78, 117, 109, 98, 101, 114, 84, 97, 98, 108,
+            101, 1, 0, 10, 83, 111, 117, 114, 99, 101,
+            70, 105, 108, 101, 1, 0, 14, 84, 101, 115,
+            116, 67, 108, 97, 115, 115, 46, 106, 97, 118,
+            97, 12, 0, 4, 0, 5, 1, 0, 9, 84,
+            101, 115, 116, 67, 108, 97, 115, 115, 1, 0,
+            16, 106, 97, 118, 97, 47, 108, 97, 110, 103,
+            47, 79, 98, 106, 101, 99, 116, 0, 33, 0,
+            2, 0, 3, 0, 0, 0, 0, 0, 1, 0,
+            1, 0, 4, 0, 5, 0, 1, 0, 6, 0,
+            0, 0, 29, 0, 1, 0, 1, 0, 0, 0,
+            5, 42, -73, 0, 1, -79, 0, 0, 0, 1,
+            0, 7, 0, 0, 0, 6, 0, 1, 0, 0,
+            0, 1, 0, 1, 0, 8, 0, 0, 0, 2,
+            0, 9 };
+
+        protected Class findClass(String name) throws ClassNotFoundException {
+            try {
+                synchronized (lock) {
+                    lock.wait();
+                }
+            } catch (InterruptedException ie) {}
+
+            if (name.equals("TestClass")) {
+                numFindClassCalled++;
+                return defineClass(null, classData, 0, classData.length);
+            } else {
+                throw new ClassNotFoundException("Class " + name + " not found.");
+            }
+        }
+    }
+    
+    static class SyncLoadTestThread extends Thread {
+        volatile boolean started;
+        ClassLoader cl;
+        Class cls;
+        
+        SyncLoadTestThread(ClassLoader cl) {
+            this.cl = cl;
+        }
+        
+        public void run() {
+            try {
+                started = true;
+                cls = Class.forName("TestClass", false, cl);
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+        }
+    }
+    
+    /**
+     * Regression test for HARMONY-1939:
+     * 2 threads simultaneously run Class.forName() method for the same classname 
+     * and the same classloader. It is expected that both threads succeed but
+     * class must be defined just once.  
+     */
+    public void test_loadClass_concurrentLoad() throws Exception 
+    {    
+        Object lock = new Object();
+        SyncTestClassLoader cl = new SyncTestClassLoader(lock);
+        SyncLoadTestThread tt1 = new SyncLoadTestThread(cl);
+        SyncLoadTestThread tt2 = new SyncLoadTestThread(cl);
+        tt1.start();
+        tt2.start();
+
+        while (!tt1.started && !tt2.started) {
+            Thread.sleep(100);
+        }
+
+        synchronized (lock) {
+            lock.notifyAll();
+        }
+        tt1.join();
+        tt2.join();
+        
+        assertSame("Bad or redefined class", tt1.cls, tt2.cls);
+        assertEquals("Both threads tried to define class", 1, cl.numFindClassCalled);
+    }
 
     /**
      * @tests java.lang.ClassLoader#getResource(java.lang.String)

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/ClassLoader.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/ClassLoader.java?view=diff&rev=501401&r1=501400&r2=501401
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/ClassLoader.java (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/ClassLoader.java Tue Jan 30 06:17:35 2007
@@ -425,16 +425,16 @@
                                     String implTitle, String implVersion,
                                     String implVendor, URL sealBase)
         throws IllegalArgumentException {
-        if (getPackage(name) != null) {
-            throw new IllegalArgumentException("Package " + name
-                + "has been already defined.");
-        }
-        Package pkg = new Package(this, name, specTitle, specVersion, specVendor,
-            implTitle, implVersion, implVendor, sealBase);
         synchronized (definedPackages) {
+            if (getPackage(name) != null) {
+                throw new IllegalArgumentException("Package " + name
+                    + "has been already defined.");
+            }
+            Package pkg = new Package(this, name, specTitle, specVersion, specVendor,
+                implTitle, implVersion, implVendor, sealBase);
             definedPackages.put(name, pkg);
+            return pkg;
         }
-        return pkg;
     }
 
     /**
@@ -518,7 +518,7 @@
     /**
      * @com.intel.drl.spec_ref
      */
-    protected Class<?> loadClass(String name, boolean resolve)
+    protected synchronized Class<?> loadClass(String name, boolean resolve)
         throws ClassNotFoundException {
         checkInitialized();
         Class<?> clazz = findLoadedClass(name);