Right now within the implementation of APIs in java.sql.DriverManager there are classloader checks to ensure whether the caller is allowed access to registered drivers. For example the getDriver(String url) API[1] calls the isDriverAllowed (private) method[2] to check if the registered driver is allowed access from the caller's classloader. The implementation of isDriverAllowed has this[3]:
aClass = Class.forName(driver.getClass().getName(), true, classLoader); Is it intentional to intialize that class by passing "true" to the forName call? The reason I ask is the following scenario: 1. Imagine a multi classloader environment. 2. Consider postgres JDBC driver (from postgres.jar) gets loaded through classloader C1 and is registered in DriverManager in context of C1. 3. Now consider a class A loaded in classloader C2. Let's say this C2 also has postgres.jar in its classpath but hasn't yet loaded any of the classes from it yet nor have any calls to "registerDriver" been made by any of the classes loaded by this C2. 4. Class A (in context of C2) now calls getDriver(String url) passing it a JDBC url corresponding to postgres. This will result in a SQLException("No suitable driver") exception and that's fine, because C2 isn't allowed access to driver registered in context of C1. However, now consider the following code(again within class A in context of C2): try { DriverManager.getDriver("jdbc:postgres:...."); } catch (SQLException e) { // expected // now lets do the same call again driver = DriverManager.getDriver("jdbc:postgres:...."); --> this one passes } So what's being done is, the SQLException("no suitable driver") is caught and the exact same call which triggered this issue, is called again. This time the call passes and returns a JDBC driver corresponding to the postgres driver. Looking at the implementation of DriverManager (which I linked before), I can understand why this happens but it just seems odd that the API would behave in this manner (that too with no indication in the documentation). What really is happening here is that the current implementation of isDriverAllowed, due to its usage of "true" to initialize the driver class ends up triggering the Driver's static block (which as per the JDBC spec) is expected/mandated to register with the DriverManager. As a result, this call ends up registering the driver, now in the context of C2 and as a result the subsequent calls to this (and other APIs) start passing from classes loaded by C2 (like that class A). Should this check in the isDriverAllowed, instead use "false" and not trigger the intialization of the class? [1] https://hg.openjdk.java.net/jdk/jdk/file/5a3b04593405/src/java.sql/share/classes/java/sql/DriverManager.java#l266 [2] https://hg.openjdk.java.net/jdk/jdk/file/5a3b04593405/src/java.sql/share/classes/java/sql/DriverManager.java#l280 [3] https://hg.openjdk.java.net/jdk/jdk/file/5a3b04593405/src/java.sql/share/classes/java/sql/DriverManager.java#l555 -Jaikiran