We're seeing a deadlock when two different threads load different DataType classes at the same time. It looks like loading one DataType class causes the others to be loaded as well during class initialization. But, this can cause a deadlock when multiple threads are trying to load these DataType classes because they each hold a lock on the class and end up waiting for the others to finish.
The following code reproduces the deadlock for me:
import java.io.*;
import java.net.*;
class jooqlock {
public static void main(String[] args) throws Exception {
for (int i = 0; i < 1; i++) {
doit();
}
}
private static void doit() throws Exception {
final ClassLoader loader = new URLClassLoader(new URL[] { new File("jooq-3.4.4.jar").toURI().toURL() });
Runnable oload = new Runnable() {
public void run() {
try {
Class.forName("org.jooq.util.sqlite.SQLiteDataType", true, loader);
} catch (Throwable th) {
th.printStackTrace();
}
}
};
Runnable sload = new Runnable() {
public void run() {
try {
Class.forName("org.jooq.util.postgres.PostgresDataType", true, loader);
} catch (Throwable th) {
th.printStackTrace();
}
}
};
Thread th1 = new Thread(oload);
Thread th2 = new Thread(sload);
th1.start();
th2.start();
th1.join();
th2.join();
}
}
Here is a stack dump from after the deadlock happens:
Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.65-b04 mixed mode):
"Thread-1" prio=5 tid=0x00007fd119841800 nid=0x5303 in Object.wait() [0x000000011b619000]
java.lang.Thread.State: RUNNABLE
at org.jooq.util.postgres.PostgresDataType.<clinit>(PostgresDataType.java:76)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:270)
at jooqlock$2.run(jooqlock.java:27)
at java.lang.Thread.run(Thread.java:745)
"Thread-0" prio=5 tid=0x00007fd119841000 nid=0x5103 in Object.wait() [0x000000011b515000]
java.lang.Thread.State: RUNNABLE
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:190)
at org.jooq.impl.SQLDataType.<clinit>(SQLDataType.java:341)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:190)
at org.jooq.impl.DefaultDataType.<clinit>(DefaultDataType.java:219)
at org.jooq.util.sqlite.SQLiteDataType.<clinit>(SQLiteDataType.java:71)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:270)
at jooqlock$1.run(jooqlock.java:18)
at java.lang.Thread.run(Thread.java:745)
We're seeing a deadlock when two different threads load different DataType classes at the same time. It looks like loading one DataType class causes the others to be loaded as well during class initialization. But, this can cause a deadlock when multiple threads are trying to load these DataType classes because they each hold a lock on the class and end up waiting for the others to finish.
The following code reproduces the deadlock for me:
Here is a stack dump from after the deadlock happens: