Hi Jaikiran
> On Feb 10, 2020, at 10:09 AM, Jaikiran Pai <jai.forums2...@gmail.com> wrote: > > 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); This dates back to JDK 1.2 (1998/99) and I would be hesitant to change this at this time > > 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? As I mentioned above, this dates back to the very early days of JDBC and JDK 1.2. Any changes in this area could be quite disruptive and would require extensive testing. > > [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 > > Best Lance <http://oracle.com/us/design/oracle-email-sig-198324.gif> <http://oracle.com/us/design/oracle-email-sig-198324.gif> <http://oracle.com/us/design/oracle-email-sig-198324.gif> <http://oracle.com/us/design/oracle-email-sig-198324.gif>Lance Andersen| Principal Member of Technical Staff | +1.781.442.2037 Oracle Java Engineering 1 Network Drive Burlington, MA 01803 lance.ander...@oracle.com <mailto:lance.ander...@oracle.com>