The memcpy() call in the clone() method in libjava/java/lang/natObject.cc copies the sync_info member (when hash synchronization is off). When the lock has been held at least once, sync_info is non-NULL and therefore the original and cloned objects are associated to the same lock. The locks should be distinct (as they are with hash synchronization on). I've confirmed this bug in 3.3.3 and 4.0.1 and it looks like it's in HEAD too. I used only configure options --enable-languages=c,c++,java --disable-hash-synchronization --prefix=... The test below starts two threads that acquire locks on two *different* objects (one the clone of the other). There is lock contention with gcj <= 4.0.1 when hash synch is disabled; however, both locks should be able to be held simultaneously. A (minimally-tested) patch to 4.0.1 follows the test class; this patch just sets sync_info to an uninitialized state in all objects that are the result of a clone(). class SynchTest { public static void main(String[] args) throws CloneNotSupportedException { // same behavior occurs with non-array objects; we use arrays because // they're easy & cloneable final Object[] o1 = new Object[0]; synchronized(o1) { System.out.println("acquired (and now releasing) o1 lock"); } final Object[] o2 = (Object[]) o1.clone(); System.out.println("cloned o1 -> o2"); System.out.println("o1 == " + o1); System.out.println("o2 == " + o2); System.out.println(); System.out.println("performing sync test..."); System.out.println("expect both locks to be held simultaneously"); new Thread() { public void run() { System.out.println("t2 entering o2 lock"); synchronized(o2) { System.out.println(" t2 entered o2 lock"); try { Thread.sleep(2000); } catch(InterruptedException ie) { ie.printStackTrace(); } System.out.println(" t2 exiting o2 lock"); } System.out.println("t2 exited o2 lock"); } }.start(); System.out.println("t1 entering o1 lock"); synchronized(o1) { System.out.println(" t1 entered o1 lock"); try { Thread.sleep(2000); } catch(InterruptedException ie) { ie.printStackTrace(); } System.out.println(" t1 exiting o1 lock"); } System.out.println("t1 exited o1 lock"); } } diff -Nurp gcc-4.0.1/libjava/java/lang/natObject.cc gcc-4.0.1-fixed/libjava/java/lang/natObject.cc --- gcc-4.0.1/libjava/java/lang/natObject.cc Fri May 13 19:43:09 2005 +++ gcc-4.0.1-fixed/libjava/java/lang/natObject.cc Fri Aug 12 05:52:54 2005 @@ -104,6 +104,10 @@ java::lang::Object::clone (void) } memcpy ((void *) r, (void *) this, size); +#ifndef JV_HASH_SYNCHRONIZATION + // guarantee that the locks associated to the two objects are distinct + r->sync_info = 0; +#endif return r; }
-- Summary: clone() copies internal lock data with hash synchronization off Product: gcc Version: 4.0.1 Status: UNCONFIRMED Severity: normal Priority: P2 Component: libgcj AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: mdeters at morgandeters dot com CC: gcc-bugs at gcc dot gnu dot org,java-prs at gcc dot gnu dot org GCC build triplet: i686-pc-linux-gnu GCC host triplet: i686-pc-linux-gnu GCC target triplet: i686-pc-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=23353