Skip to content

Deadlock when loading DataType classes #3777

@tstack

Description

@tstack

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)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions