首页 > 解决方案 > Why does jdbc DriverManager getConnection() need synchronized(DriverManager.class)?

问题描述

ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
synchronized(DriverManager.class) {
    // synchronize loading of the correct classloader.
    if (callerCL == null) {
        callerCL = Thread.currentThread().getContextClassLoader();
    }
}

I don't understand the comments, When will the correct classloader not be loaded?</p>

标签: jdbcdriver

解决方案


It does not seem to serve a purpose, and this synchronized-block was removed in later Java versions. It is present in Java 8 update 275, but is not present in Java 11.0.9 (my guess is that it was removed in Java 9).

To me, it looks like a leftover from code that initialized a field instead of a local variable, or possibly it used to address other concurrency concerns. In Java 8, a number of (static) DriverManager methods (registerDriver and deregisterDriver) were defined as sychronized, so it is possible this served to establish a happens-before relation between those methods and the getConnection method. However, as driver registrations are stored in a CopyOnWriteArrayList, it would be unnecessary to establish such a happens-before relation; in older Java versions however, this likely was a plain ArrayList, so then it might have needed the happens-before.

However, I don't want to do code-archeology on older Java versions to confirm either of those theories.

So, in short: it is unnecessary and was removed in later Java versions.

Java 8 fragment:

//  Worker method called by the public getConnection() methods.
private static Connection getConnection(
    String url, java.util.Properties info, Class<?> caller) throws SQLException {
    /*
     * When callerCl is null, we should check the application's
     * (which is invoking this class indirectly)
     * classloader, so that the JDBC driver class outside rt.jar
     * can be loaded from here.
     */
    ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
    synchronized(DriverManager.class) {
        // synchronize loading of the correct classloader.
        if (callerCL == null) {
            callerCL = Thread.currentThread().getContextClassLoader();
        }
    }

    if(url == null) {
        throw new SQLException("The url cannot be null", "08001");
    }

Java 11 fragment

//  Worker method called by the public getConnection() methods.
private static Connection getConnection(
    String url, java.util.Properties info, Class<?> caller) throws SQLException {
    /*
     * When callerCl is null, we should check the application's
     * (which is invoking this class indirectly)
     * classloader, so that the JDBC driver class outside rt.jar
     * can be loaded from here.
     */
    ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
    if (callerCL == null || callerCL == ClassLoader.getPlatformClassLoader()) {
        callerCL = Thread.currentThread().getContextClassLoader();
    }

    if (url == null) {
        throw new SQLException("The url cannot be null", "08001");
    }

推荐阅读