使用 `classloader.close` 时发生了什么?

问题描述 投票:0回答:1

我发现原因是我用

classloader.close()
.

这是错误代码。

错误: java.lang.NoClassDefFoundError:org/postgresql/Driver$1

    try (URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] {new URL("file:///" + uriPath)}, Thread.currentThread().getContextClassLoader())) {
        Class<?> clazz = classLoader.loadClass(driverClassName);
        if (clazz.newInstance() instanceof Driver) {
            Driver driver = (Driver) clazz.newInstance();
            return driver;
        }
    } catch (Exception e) {
        log.error("error");
    }

当我不使用 try-with-resource 时,这个错误就消失了。 正确的代码:

    try {
        ClassLoader ctxClassloader = Thread.currentThread().getContextClassLoader();
        URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] {new URL("file:///" + uriPath)},
            ctxClassloader);
        Class<?> clazz = classLoader.loadClass(driverClassName);
        if (clazz.newInstance() instanceof Driver) {
            Driver driver = (Driver) clazz.newInstance();
            return driver;
        }
    } catch (Exception e) {
        log.error("error");
    }

这就是我使用驱动程序的方式。我在springboot中使用它。

Driver driver = getDriver(xx);
JdbcTemplate jdbcTemplate = new JdbcTemplate(new SimpleDriverDataSource(driver, "xx", properties));
String s = jdbcTemplate.queryForObject("select VERSION()", String.class); //error happens

谁能告诉我原因吗?为什么使用

classloader.close()
后,显示
java.lang.NoClassDefFoundError
。谢谢你! :)

java jdbc classloader
1个回答
0
投票

URLClassLoader.close()
的 JavaDoc 描述了它的功能:

关闭这个

URLClassLoader
,这样它就不能再用于加载这个加载器定义的新类或资源。委托层次结构中此加载器的任何父代定义的类和资源仍然可以访问。此外,任何已经加载的类或资源仍然可以访问。

当您通过类加载器创建

Driver
的实例时,JVM 将仅加载加载驱动程序和实例化驱动程序所需的最少数量的类。

仅在(例如)使用您的驱动程序打开 JDBC 连接时才需要的其他类尚未加载 - 它们在需要时加载(即打开 JDBC 连接时)。

当您在实例化驱动程序后关闭类加载器时,它不能再用于加载该类,因此您会看到

java.lang.NoClassDefFoundError
:您的类加载器无法加载该类,因为类加载器已关闭,并且它的父类加载器没有那个班级。

© www.soinside.com 2019 - 2024. All rights reserved.