JDBC 驱动程序注册死锁?
JDBC Driver Registration Deadlock?
在一个线程中,正在创建一只 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.next(ServiceLoader.java:480)
at java.sql.DriverManager.run(DriverManager.java:603)
at java.sql.DriverManager.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)
None的线程正在完成它的任务,不知道为什么。初始化 JDBC 驱动程序的方式有什么问题吗?
查看堆栈跟踪,问题似乎出在 JackRabbit
- 正在加载 Derby 嵌入式驱动程序 class、
- 触发注册,
- 触发class加载
java.sql.DriverManager
,
- 触发
java.sql.DriverManager
通过JDBC4服务加载机制加载驱动,
- 这会触发 Derby 嵌入式驱动程序实例的构造,它必须等到 class第 1 步的加载完成。
由于class加载是不可重入的(据我所知),这导致一切都停止了。 DriverManager
的加载等待等待 DriverManager
的 Derby 驱动程序。当您随后还尝试加载 PostgreSQL 驱动程序时,它还必须等待 DriverManager
.
这是导致此问题的理论,我可能是错的(因为如果这个理论是正确的,我希望它是一个更常见的问题)。我会做一些测试,看看我是否可以重现这个,如果有必要,将它报告给 Oracle。
解决此问题的真正方法是不使用 Class.forName
加载驱动程序,而是依赖于 JDBC 驱动程序自动加载。然而,这似乎确实指出了 DriverManager
工作方式的缺陷。
一种解决方法是确保 java.sql.DriverManager
已经在 [=19] 之前的一些初始化代码中被 class 加载(例如,通过调用其方法之一(例如 DriverManager.getLoginTimeout()
) =] 被调用。
另一种解决方法是修改您的 JDBC 驱动程序 jar 并删除 /META-INF/services/java.sql.Driver
文件;这将禁用驱动程序自动加载。
在一个线程中,正在创建一只 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.next(ServiceLoader.java:480)
at java.sql.DriverManager.run(DriverManager.java:603)
at java.sql.DriverManager.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)
None的线程正在完成它的任务,不知道为什么。初始化 JDBC 驱动程序的方式有什么问题吗?
查看堆栈跟踪,问题似乎出在 JackRabbit
- 正在加载 Derby 嵌入式驱动程序 class、
- 触发注册,
- 触发class加载
java.sql.DriverManager
, - 触发
java.sql.DriverManager
通过JDBC4服务加载机制加载驱动, - 这会触发 Derby 嵌入式驱动程序实例的构造,它必须等到 class第 1 步的加载完成。
由于class加载是不可重入的(据我所知),这导致一切都停止了。 DriverManager
的加载等待等待 DriverManager
的 Derby 驱动程序。当您随后还尝试加载 PostgreSQL 驱动程序时,它还必须等待 DriverManager
.
这是导致此问题的理论,我可能是错的(因为如果这个理论是正确的,我希望它是一个更常见的问题)。我会做一些测试,看看我是否可以重现这个,如果有必要,将它报告给 Oracle。
解决此问题的真正方法是不使用 Class.forName
加载驱动程序,而是依赖于 JDBC 驱动程序自动加载。然而,这似乎确实指出了 DriverManager
工作方式的缺陷。
一种解决方法是确保 java.sql.DriverManager
已经在 [=19] 之前的一些初始化代码中被 class 加载(例如,通过调用其方法之一(例如 DriverManager.getLoginTimeout()
) =] 被调用。
另一种解决方法是修改您的 JDBC 驱动程序 jar 并删除 /META-INF/services/java.sql.Driver
文件;这将禁用驱动程序自动加载。