Skip to content

ContextClassLoader load priority problem in DriverDataSource #2319

@yx91490

Description

@yx91490

DriverDataSource has several load methods which load in the order:

  1. load from registered drivers in DriverManager
  2. load from ContextClassLoader
  3. load from DriverDataSource's classloader
  4. load by connection url from DriverManager

the 4th load method is the same with the 1st essentially.

Suppose we have two conflict JDBC Drivers(they have the same class name but different implementations), we normally prefer the 2nd load method by ContextClassLoader to load the expected one. But if DriverManager already load the conflicted one, as the 1st load method's priority is higher than the 2nd, we would never have the opportunity to load the exected Driver.

A real example of conflicted drivers is org.opengauss:opengauss-jdbc and org.postgresql:postgresql, the coresponding codes are:

<!-- pom.xml -->
<dependencies>
    <dependency>
        <groupId>org.opengauss</groupId>
        <artifactId>opengauss-jdbc</artifactId>
        <version>5.1.0</version>
    </dependency>
    <dependency>
        <groupId>com.zaxxer</groupId>
        <artifactId>HikariCP</artifactId>
        <version>6.3.0</version>
    </dependency>
</dependencies>
// Demo.java
Class.forName("org.postgresql.Driver");
URL url = new URL("https://repo1.maven.org/maven2/org/postgresql/postgresql/42.7.6/postgresql-42.7.6.jar");
URLClassLoader loader = new ChildFirstClassLoader(new URL[] {url}, ClassLoader.getSystemClassLoader());
Thread.currentThread().setContextClassLoader(loader);
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:postgresql://localhost:5432/postgres");
config.setUsername("postgres");
config.setPassword("");
config.setDriverClassName("org.postgresql.Driver");
HikariDataSource datasource = new HikariDataSource(config);
try (Connection connection = datasource.getConnection()) {
    System.out.println("connection = " + connection);
}
datasource.close();

The Demo.java will load opengauss's Driver although we declared a ChildFirstClassLoader.

the solution maybe remove the 1st load method.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions