FULL PRODUCT VERSION :
on Linux:
java version "1.7.0_25"
Java(TM) SE Runtime Environment (build 1.7.0_25-b15)
Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode)
on OSX:
java version "1.6.0_37"
Java(TM) SE Runtime Environment (build 1.6.0_37-b06-434)
Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01-434, mixed mode)
FULL OS VERSION :
OSX, Linux
A DESCRIPTION OF THE PROBLEM :
If you define a class with a static field that depends on a subclass of that class, there is an opportunity for deadlock when multiple threads try to load the class and its subclass.
A reproducible test case is included.
A search of the bug database gave two results, both somewhat old and closed as won't fix:
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4891511
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4295661
THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: Did not try
THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Did not try
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
$ javac ClassDeadlockTest.java
$ java ClassDeadlockTest 500
JVM will deadlock with a thread in ClassDeadlockTest.Super.<clinit>
while main thread is waiting to load ClassDeadlockTest.Sub
EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected: Program will terminate
Actual: Program deadlocks and hangs
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Thread dump:
Full thread dump Java HotSpot(TM) 64-Bit Server VM (23.25-b01 mixed mode):
"Thread-0" prio=10 tid=0x00007f624410d800 nid=0x72c5 in Object.wait() [0x00007f623131e000]
java.lang.Thread.State: RUNNABLE
at ClassDeadlockTest$Super.getHelloString(ClassDeadlockTest.java:43)
at ClassDeadlockTest$Super.<clinit>(ClassDeadlockTest.java:32)
at ClassDeadlockTest$1.run(ClassDeadlockTest.java:16)
"Service Thread" daemon prio=10 tid=0x00007f62440f0800 nid=0x72c3 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" daemon prio=10 tid=0x00007f62440ee000 nid=0x72c2 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" daemon prio=10 tid=0x00007f62440eb000 nid=0x72c1 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" daemon prio=10 tid=0x00007f62440e9000 nid=0x72c0 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" daemon prio=10 tid=0x00007f624409a800 nid=0x72bf in Object.wait() [0x00007f6231924000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000007cc765798> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
- locked <0x00000007cc765798> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:189)
"Reference Handler" daemon prio=10 tid=0x00007f6244098000 nid=0x72be in Object.wait() [0x00007f62401a7000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000007cc765320> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:503)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
- locked <0x00000007cc765320> (a java.lang.ref.Reference$Lock)
"main" prio=10 tid=0x00007f6244007800 nid=0x72b8 in Object.wait() [0x00007f6248902000]
java.lang.Thread.State: RUNNABLE
at ClassDeadlockTest.main(ClassDeadlockTest.java:27)
"VM Thread" prio=10 tid=0x00007f6244090800 nid=0x72bd runnable
"GC task thread#0 (ParallelGC)" prio=10 tid=0x00007f6244015000 nid=0x72b9 runnable
"GC task thread#1 (ParallelGC)" prio=10 tid=0x00007f6244017000 nid=0x72ba runnable
"GC task thread#2 (ParallelGC)" prio=10 tid=0x00007f6244018800 nid=0x72bb runnable
"GC task thread#3 (ParallelGC)" prio=10 tid=0x00007f624401a800 nid=0x72bc runnable
"VM Periodic Task Thread" prio=10 tid=0x00007f62440fb000 nid=0x72c4 waiting on condition
JNI global references: 110
Heap
PSYoungGen total 46144K, used 1582K [0x00000007cc760000, 0x00000007cfae0000, 0x0000000800000000)
eden space 39552K, 4% used [0x00000007cc760000,0x00000007cc8eb8d8,0x00000007cee00000)
from space 6592K, 0% used [0x00000007cf470000,0x00000007cf470000,0x00000007cfae0000)
to space 6592K, 0% used [0x00000007cee00000,0x00000007cee00000,0x00000007cf470000)
ParOldGen total 105600K, used 0K [0x0000000765600000, 0x000000076bd20000, 0x00000007cc760000)
object space 105600K, 0% used [0x0000000765600000,0x0000000765600000,0x000000076bd20000)
PSPermGen total 21248K, used 2471K [0x0000000760400000, 0x00000007618c0000, 0x0000000765600000)
object space 21248K, 11% used [0x0000000760400000,0x0000000760669d30,0x00000007618c0000)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
/**
* @author Curtis Caravone
*/
public class ClassDeadlockTest {
public static void main(String[] args) {
if (args.length != 1) {
throw new RuntimeException("Usage: ClassDeadlockTest delay_millis (try 500 and 1500)");
}
int delayMillis = Integer.valueOf(args[0]);
System.out.println("Delay = " + delayMillis + " millis");
new Thread() {
@Override
public void run() {
System.out.println(Thread.currentThread() + "Created super: " + new Super());
}
}.start();
try {
Thread.sleep(delayMillis);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread() + "Creating sub...");
System.out.println(Thread.currentThread() + "Created sub: " + new Sub());
}
public static class Super {
public static final String hello = getHelloString();
private static String getHelloString() {
int sleepTime = 1000;
System.out.println(Thread.currentThread() + "Sleeping in Super static init for " + sleepTime + " millis");
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread() + "Creating new Sub()");
return "Sub Instance = " + new Sub();
}
}
public static class Sub extends Super {
public Sub() {
System.out.println(Thread.currentThread() + "In Sub constructor");
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Rewrite class definition so that static initializers don't reference subclasses.
on Linux:
java version "1.7.0_25"
Java(TM) SE Runtime Environment (build 1.7.0_25-b15)
Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode)
on OSX:
java version "1.6.0_37"
Java(TM) SE Runtime Environment (build 1.6.0_37-b06-434)
Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01-434, mixed mode)
FULL OS VERSION :
OSX, Linux
A DESCRIPTION OF THE PROBLEM :
If you define a class with a static field that depends on a subclass of that class, there is an opportunity for deadlock when multiple threads try to load the class and its subclass.
A reproducible test case is included.
A search of the bug database gave two results, both somewhat old and closed as won't fix:
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4891511
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4295661
THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: Did not try
THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Did not try
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
$ javac ClassDeadlockTest.java
$ java ClassDeadlockTest 500
JVM will deadlock with a thread in ClassDeadlockTest.Super.<clinit>
while main thread is waiting to load ClassDeadlockTest.Sub
EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected: Program will terminate
Actual: Program deadlocks and hangs
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Thread dump:
Full thread dump Java HotSpot(TM) 64-Bit Server VM (23.25-b01 mixed mode):
"Thread-0" prio=10 tid=0x00007f624410d800 nid=0x72c5 in Object.wait() [0x00007f623131e000]
java.lang.Thread.State: RUNNABLE
at ClassDeadlockTest$Super.getHelloString(ClassDeadlockTest.java:43)
at ClassDeadlockTest$Super.<clinit>(ClassDeadlockTest.java:32)
at ClassDeadlockTest$1.run(ClassDeadlockTest.java:16)
"Service Thread" daemon prio=10 tid=0x00007f62440f0800 nid=0x72c3 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" daemon prio=10 tid=0x00007f62440ee000 nid=0x72c2 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" daemon prio=10 tid=0x00007f62440eb000 nid=0x72c1 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" daemon prio=10 tid=0x00007f62440e9000 nid=0x72c0 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" daemon prio=10 tid=0x00007f624409a800 nid=0x72bf in Object.wait() [0x00007f6231924000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000007cc765798> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
- locked <0x00000007cc765798> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:189)
"Reference Handler" daemon prio=10 tid=0x00007f6244098000 nid=0x72be in Object.wait() [0x00007f62401a7000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000007cc765320> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:503)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
- locked <0x00000007cc765320> (a java.lang.ref.Reference$Lock)
"main" prio=10 tid=0x00007f6244007800 nid=0x72b8 in Object.wait() [0x00007f6248902000]
java.lang.Thread.State: RUNNABLE
at ClassDeadlockTest.main(ClassDeadlockTest.java:27)
"VM Thread" prio=10 tid=0x00007f6244090800 nid=0x72bd runnable
"GC task thread#0 (ParallelGC)" prio=10 tid=0x00007f6244015000 nid=0x72b9 runnable
"GC task thread#1 (ParallelGC)" prio=10 tid=0x00007f6244017000 nid=0x72ba runnable
"GC task thread#2 (ParallelGC)" prio=10 tid=0x00007f6244018800 nid=0x72bb runnable
"GC task thread#3 (ParallelGC)" prio=10 tid=0x00007f624401a800 nid=0x72bc runnable
"VM Periodic Task Thread" prio=10 tid=0x00007f62440fb000 nid=0x72c4 waiting on condition
JNI global references: 110
Heap
PSYoungGen total 46144K, used 1582K [0x00000007cc760000, 0x00000007cfae0000, 0x0000000800000000)
eden space 39552K, 4% used [0x00000007cc760000,0x00000007cc8eb8d8,0x00000007cee00000)
from space 6592K, 0% used [0x00000007cf470000,0x00000007cf470000,0x00000007cfae0000)
to space 6592K, 0% used [0x00000007cee00000,0x00000007cee00000,0x00000007cf470000)
ParOldGen total 105600K, used 0K [0x0000000765600000, 0x000000076bd20000, 0x00000007cc760000)
object space 105600K, 0% used [0x0000000765600000,0x0000000765600000,0x000000076bd20000)
PSPermGen total 21248K, used 2471K [0x0000000760400000, 0x00000007618c0000, 0x0000000765600000)
object space 21248K, 11% used [0x0000000760400000,0x0000000760669d30,0x00000007618c0000)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
/**
* @author Curtis Caravone
*/
public class ClassDeadlockTest {
public static void main(String[] args) {
if (args.length != 1) {
throw new RuntimeException("Usage: ClassDeadlockTest delay_millis (try 500 and 1500)");
}
int delayMillis = Integer.valueOf(args[0]);
System.out.println("Delay = " + delayMillis + " millis");
new Thread() {
@Override
public void run() {
System.out.println(Thread.currentThread() + "Created super: " + new Super());
}
}.start();
try {
Thread.sleep(delayMillis);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread() + "Creating sub...");
System.out.println(Thread.currentThread() + "Created sub: " + new Sub());
}
public static class Super {
public static final String hello = getHelloString();
private static String getHelloString() {
int sleepTime = 1000;
System.out.println(Thread.currentThread() + "Sleeping in Super static init for " + sleepTime + " millis");
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread() + "Creating new Sub()");
return "Sub Instance = " + new Sub();
}
}
public static class Sub extends Super {
public Sub() {
System.out.println(Thread.currentThread() + "In Sub constructor");
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Rewrite class definition so that static initializers don't reference subclasses.