ADDITIONAL SYSTEM INFORMATION :
macOS Montery 12.6
java version "11.0.14" 2022-01-18 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.14+8-LTS-263)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.14+8-LTS-263, mixed mode)
A DESCRIPTION OF THE PROBLEM :
## Background
My test project run on JDK 11. Dependencies include Derby and H2 JDBC driver.
When `DriverManager.getDriver` is called, JDBC drivers SPI loaded by ServiceLoader is in order, Derby and then H2 on my machine.
If loading Derby driver throws exception, then H2 driver will not be loaded any more.
Related code:
```
DriverManager.ensureDriversInitialized
ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
Iterator<Driver> driversIterator = loadedDrivers.iterator();
// ...
try {
while (driversIterator.hasNext()) {
driversIterator.next();
}
} catch (Throwable t) {
// Do nothing
}
```
The try catch block includes whole while loop, any `driversIterator.next()` failure will break while loop.
I searched in bug database, there is a similar one: https://bugs.openjdk.org/browse/JDK-8190759 , but it was closed and unresolved.
## Reproduce steps
Gradle dependencies:
```
compile 'org.apache.derby:derby:10.16.1.1' // class file version 61.0, compile by JDK 17
compile 'com.h2database:h2:2.2.224'
```
Test code:
```
public class DriverManagerTest {
@Test
public void testGetDriverFailedOfClassVersion() throws SQLException {
DriverManager.getDriver("jdbc:h2:mem:test1;DATABASE_TO_UPPER=false;MODE=MySQL");
}
}
```
Run result:
```
java.sql.SQLException: No suitable driver
at java.sql/java.sql.DriverManager.getDriver(DriverManager.java:298)
at jdbc.DriverManagerTest.testGetDriverFailedOfClassVersion(DriverManagerTest.java:13)
```
When I debug on DriverManager, the thrown exception message is:
```
java.lang.UnsupportedClassVersionError: org/apache/derby/iapi/jdbc/AutoloadedDriver has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 55.0
```
The reason is Derby driver is compile by JDK 17, but my local JDK is version 11.
## Possible solution
Move try catch block into while loop in DriverManager.ensureDriversInitialized, e.g.
```
while (driversIterator.hasNext()) {
try {
driversIterator.next();
} catch (Throwable t) {
// Do nothing
}
}
```
## Motivation
Currently, when error occur, there is no any error message, just show `SQLException: No suitable driver`, it is confusing.
If it ignore invalid driver and keep initialize other drivers, then user program still works on valid drivers. It might be robuster than before.
macOS Montery 12.6
java version "11.0.14" 2022-01-18 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.14+8-LTS-263)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.14+8-LTS-263, mixed mode)
A DESCRIPTION OF THE PROBLEM :
## Background
My test project run on JDK 11. Dependencies include Derby and H2 JDBC driver.
When `DriverManager.getDriver` is called, JDBC drivers SPI loaded by ServiceLoader is in order, Derby and then H2 on my machine.
If loading Derby driver throws exception, then H2 driver will not be loaded any more.
Related code:
```
DriverManager.ensureDriversInitialized
ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
Iterator<Driver> driversIterator = loadedDrivers.iterator();
// ...
try {
while (driversIterator.hasNext()) {
driversIterator.next();
}
} catch (Throwable t) {
// Do nothing
}
```
The try catch block includes whole while loop, any `driversIterator.next()` failure will break while loop.
I searched in bug database, there is a similar one: https://bugs.openjdk.org/browse/JDK-8190759 , but it was closed and unresolved.
## Reproduce steps
Gradle dependencies:
```
compile 'org.apache.derby:derby:10.16.1.1' // class file version 61.0, compile by JDK 17
compile 'com.h2database:h2:2.2.224'
```
Test code:
```
public class DriverManagerTest {
@Test
public void testGetDriverFailedOfClassVersion() throws SQLException {
DriverManager.getDriver("jdbc:h2:mem:test1;DATABASE_TO_UPPER=false;MODE=MySQL");
}
}
```
Run result:
```
java.sql.SQLException: No suitable driver
at java.sql/java.sql.DriverManager.getDriver(DriverManager.java:298)
at jdbc.DriverManagerTest.testGetDriverFailedOfClassVersion(DriverManagerTest.java:13)
```
When I debug on DriverManager, the thrown exception message is:
```
java.lang.UnsupportedClassVersionError: org/apache/derby/iapi/jdbc/AutoloadedDriver has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 55.0
```
The reason is Derby driver is compile by JDK 17, but my local JDK is version 11.
## Possible solution
Move try catch block into while loop in DriverManager.ensureDriversInitialized, e.g.
```
while (driversIterator.hasNext()) {
try {
driversIterator.next();
} catch (Throwable t) {
// Do nothing
}
}
```
## Motivation
Currently, when error occur, there is no any error message, just show `SQLException: No suitable driver`, it is confusing.
If it ignore invalid driver and keep initialize other drivers, then user program still works on valid drivers. It might be robuster than before.
- relates to
-
JDK-8190759 a jdbc auto load driver bug
- Closed