JDBC DriverManager never updated for system classloader?

Alan Bateman alan.bateman at oracle.com
Sun Nov 2 09:07:55 UTC 2025


On 27/10/2025 20:06, Charles Oliver Nutter wrote:
> Hello!
>
> I've been looking for a concrete explanation for why the JDBC 
> DriverManager can't find drivers under the following circumstances:
>
> * Driver jar loaded into child classloader of app classloader
> * Child classloader set for current thread's context classloader
>
> My long explanation of the issue is here:
>
> https://github.com/jruby/jruby/issues/8910#issuecomment-3453029437
>
> The short explanation is that when the DriverManager goes to check for 
> "allowed" drivers, it ends up using the wrong classloader.
>
> https://github.com/openjdk/jdk/blob/8151251fa683459e57430abf8e3583c444315746/src/java.sql/share/classes/java/sql/DriverManager.java#L157
>
> * Caller's class is acquired with Reflection.getCallerClass
> * Caller's classloader is acquired
> * If that classloader is null, as it would have been for classes 
> loaded on the root classpath in Java 8, it instead uses the thread 
> context classloader.
> * If that classloader is not null (Java 9+) and not the platform 
> classloader, it is used for verification; in this case it is the 
> system classloader (a "ClassLoader#AppClassLoader" instance) so the 
> child classloader's driver is disallowed.
>
> My confusion is why this code was never patched for the change to the 
> system classloader (from null to an AppClassLoader). The logic in 
> DriverManager will never use the ThreadContext classloader now, since 
> there's almost no cases where "getClassLoader" will return null.
>
> Is there a good explanation for why this code still checks for a null 
> classloader?
>

The java.sql module is mapped to the platform class loader so you are 
correct that none of the classes in that module will be visible to the 
boot class loader. None of the core modules `requires java.sql` so 
wouldn't compile anyway.

The edge case of a JNI attached thread calling DriverManager methods 
with no java frames on the stack should be the only case now where the 
caller is null.  The java.sql.rowset (requires java.sql) is also mapped 
to the platform class loader. I don't know if it uses DriverManager but 
if it did, then the caller would be a class defined by the platform 
class loader.

I don't think it's possible to engage on the question as to why 
DriverManager does a visibility check.  The discovery and and driver 
registration in this API date back to early JDK releases and have been 
very problematic to secure.  I think (need Lance to confirm) that the 
hope was that the eco system would move to DataSource but it seems there 
is still a lot of usage of DriverManager.

-Alan


More information about the core-libs-dev mailing list