JDBC驱动程序注册死锁?

6

在一个线程中,正在创建一个JackRabbit:

"docs-on-startup" #32 prio=5 os_prio=0 tid=0x00007f730d73e800 nid=0x601d in Object.wait() [0x00007f725bffc000]
   java.lang.Thread.State: RUNNABLE
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at java.lang.Class.newInstance(Class.java:442)
    at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:380)
    at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
    at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
    at java.sql.DriverManager$2.run(DriverManager.java:603)
    at java.sql.DriverManager$2.run(DriverManager.java:583)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.sql.DriverManager.loadInitialDrivers(DriverManager.java:583)
    at java.sql.DriverManager.<clinit>(DriverManager.java:101)
    at org.apache.derby.jdbc.EmbeddedDriver.boot(Unknown Source)
    at org.apache.derby.jdbc.EmbeddedDriver.<clinit>(Unknown Source)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at org.apache.jackrabbit.core.util.db.ConnectionFactory.getDriverClass(ConnectionFactory.java:261)
    at org.apache.jackrabbit.core.util.db.ConnectionFactory.createDataSource(ConnectionFactory.java:234)
    at org.apache.jackrabbit.core.util.db.ConnectionFactory.getDataSource(ConnectionFactory.java:170)
    - locked <0x000000066c71ea70> (a java.lang.Object)
    at org.apache.jackrabbit.core.persistence.pool.BundleDbPersistenceManager.getDataSource(BundleDbPersistenceManager.java:569)
    at org.apache.jackrabbit.core.persistence.pool.BundleDbPersistenceManager.init(BundleDbPersistenceManager.java:537)
    at org.apache.jackrabbit.core.persistence.pool.DerbyPersistenceManager.init(DerbyPersistenceManager.java:250)
    at org.apache.jackrabbit.core.RepositoryImpl.createPersistenceManager(RepositoryImpl.java:1375)
    at org.apache.jackrabbit.core.RepositoryImpl.createVersionManager(RepositoryImpl.java:512)
    at org.apache.jackrabbit.core.RepositoryImpl.<init>(RepositoryImpl.java:313)
    at org.apache.jackrabbit.core.RepositoryImpl.create(RepositoryImpl.java:615)

在另一个线程中,使用Class.forName("org.postgresql.Driver")初始化Postgres驱动程序的驱动程序:

"schema-task-1" #37 prio=5 os_prio=0 tid=0x00007f725402b000 nid=0x6021 in Object.wait() [0x00007f725baf9000]
   java.lang.Thread.State: RUNNABLE
    at org.postgresql.Driver.register(Driver.java:730)
    at org.postgresql.Driver.<clinit>(Driver.java:70)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)

没有线程完成其任务,不确定是否理解原因。初始化JDBC驱动程序的方式有问题吗?

1个回答

10
查看堆栈跟踪,问题似乎是JackRabbit正在加载Derby嵌入式驱动程序类,这将触发注册,从而触发java.sql.DriverManager的类加载,使java.sql.DriverManager通过JDBC 4服务加载程序机制加载驱动程序,从而触发Derby嵌入式驱动程序实例的构建,必须等到步骤1的类加载完成后才能继续进行。由于我认为类加载不可重入,因此这会导致一切陷入停滞状态。 DriverManager的加载等待Derby驱动程序,而Derby驱动程序则在等待DriverManager。当尝试加载PostgreSQL驱动程序时,它也必须等待DriverManager。

这是导致此问题的一个理论,并且我可能是错误的(因为如果这个理论正确,我希望它是一个更常见的问题)。我将进行一些测试,以查看是否可以重现此问题,并在必要时向Oracle报告此问题。

真正修复此问题的方法是不使用Class.forName加载驱动程序,而是依赖于JDBC驱动程序自动加载。但是,这确实指出了DriverManager的工作方式存在缺陷。

一种解决方法可能是确保已经加载了java.sql.DriverManager(例如,在调用一些初始化代码中的其​​中一个方法(例如DriverManager.getLoginTimeout())之前)

另一种解决方法可能是修改JDBC驱动程序jar并删除/META-INF/services/java.sql.Driver文件;这将禁用驱动程序自动加载。


2
感谢您的反馈:在启动这两个线程之前添加DriverManager.getDrivers()似乎可以解决这个问题。 - Marc Polizzi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接