如何解决为什么无法在 Java 11 中使用 URLClassloader(name, null) 加载 java.sql.Driver
在 Java 8 中,我们可以像这样加载 MysqL 驱动程序:
urlclassloader MysqL5ClassLoader = new urlclassloader(new URL[]{new File(MysqL5path).toURI().toURL()},null);
Class<?> MysqL5Class = MysqL5ClassLoader.loadClass("com.MysqL.jdbc.Driver");
Driver MysqL5Driver = (Driver) MysqL5Class.getDeclaredConstructor().newInstance();
但是在 Java 11(实际上是 9 或更高版本)中,我们必须使用
urlclassloader MysqL5ClassLoader = new urlclassloader(new URL[]{new File(MysqL5path).toURI().toURL()},ClassLoader.getPlatformClassLoader());
我检查了 oracle 文档,发现 https://docs.oracle.com/en/java/javase/11/migrate/index.html#JSMIG-GUID-A868D0B9-026F-4D46-B979-901834343F9E
在 JDK 9 中实现的更改可能会影响创建类加载器的代码,这些类加载器将 null(即引导类加载器)作为父类加载器,并假设所有平台类对父类都是可见的。此类代码可能需要更改以使用平台类加载器作为父级(请参阅 ClassLoader.getPlatformClassLoader)。
然后我用 ClassLoader.findClass(name) 用 null
parent 和 ClassLoader.getPlatformClassLoader()
parent 调试,一个得到 java.lang.NoClassDefFoundError: java/sql/Driver
,一个可以成功加载 MysqL Driver。
为什么以及如何得到不同的结果
解决方法
如果您使用 null
作为父类加载器,您是在告诉这个类加载器解析引导类加载器中的平台类。
这(通常)在 Java 9 之前有效,因为所有 Java 平台类都是通过引导类加载器加载的。
它(通常)从 Java 9 开始就不起作用了,因为在 Java 9 中他们引入了模块并改变了哪些类加载器加载了哪些平台类。大多数平台类现在由不同的类加载器加载。 (特别是由 getPlatformClassLoader()
返回的类加载器。)
所以……在 Java 9 中……如果您创建一个带有 null
父级的类加载器,那么加载 JDBC 驱动程序的类很可能会失败……因为引导类加载器不知道驱动程序依赖的平台类。
这只是您问题中引用文本内容的扩展。
问:他们为什么要改变它?
A:因为有必要支持模块并解决 SE 库单一的问题。
问:你能避免修复你的代码吗?
A:如果您想像这样动态地创建类加载器,则不会。但是如果您只是将驱动程序包含在启动时类路径中,您就不会遇到这个问题;例如使用 -cp ...
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。