2016-04-28 5 views
3

В одном нить, Jackrabbit создается:JDBC водитель регистрации Deadlock?

"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) 

и в другом потоке, драйвер для Postgres инициализируется с помощью Class.forName ("org.postgresql.Driver"):

"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?

ответ

5

Глядя на StackTrace, проблема, кажется, что Jackrabbit

  1. загружается встроенный класс драйвера Derby,
  2. , который запускает регистрацию,
  3. , который запускает загрузку классов из java.sql.DriverManager,
  4. , который запускает java.sql.DriverManager для загрузки драйвера через механизм загрузчика JDBC 4,
  5. , который запускает построение Derby embedded d речной экземпляр, который должен дождаться завершения загрузки класса 1.

Поскольку классная загрузка не является реентерабельной (насколько я знаю), это заставляет все зайти в тупик. Погрузка DriverManager ждет драйвера Derby, ожидающего DriverManager. Когда вы также пытаетесь загрузить драйвер PostgreSQL, он также должен ждать DriverManager.

Это теория того, что вызывает это, и я могу ошибаться (потому что, если эта теория правильная, я ожидаю, что это будет более распространенная проблема). Я сделаю некоторое тестирование, чтобы проверить, могу ли я воспроизвести это и, если необходимо, сообщить об этом Oracle.

Реальный способ исправить это - не загружать драйверы с использованием Class.forName, но зависит от автозагрузки драйвера JDBC. Однако это, похоже, указывает на недостаток в том, как работает DriverManager.

Обходной может быть, чтобы гарантировать, что java.sql.DriverManager уже classloaded (например, путем вызова одного из его методов (например DriverManager.getLoginTimeout()) в какой-то код инициализации перед тем RepositoryImpl.create называется.

Другой обходной путь может быть модифицировать драйвер JDBC jar (s) и удалить файл /META-INF/services/java.sql.Driver, это отключит автозагрузку драйвера.

+0

Thx для ввода: добавление DriverManager.getDrivers() перед запуском двух потоков, похоже, устраняет проблему. –