为什么在使用自定义类加载器时出现 java.lang.NoClassDefFoundError: java/sql/Driver?

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

这适用于 Java 8:

public class Test {
  public static void main(String[] args) throws Exception {
    URLClassLoader loader = new URLClassLoader(new URL[0], null);
    System.out.println("" + loader.loadClass("java.sql.Driver"));
  }
}

但是使用 Java 17 会抛出 ClassNotFoundException:

Exception in thread "main" java.lang.ClassNotFoundException: java.sql.Driver
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:592)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
    at Test.main(Test.java:16)

Java 17 的优秀类加载器图:

https://medium.com/@wakefulinsomnia/how-does-java-classloader-system-work-82eaf378f73b

相关/类似问题:

java classloader java-17 java-module urlclassloader
1个回答
0
投票

我目前的理解是,如果使用 null 父级,实际上只有 java 基类加上 URL[] 参数中的类可用。

如果还需要“java.sql”等模块中的“非基本”类,那么至少需要使用

jdk.internal.loader.ClassLoaders$PlatformClassLoader
作为父类。

public class Test {
  public static void main(String[] args) throws Exception  {
    System.out.println("java.version                                              : " + System.getProperty("java.version"));
    System.out.println("Test.class.getClassLoader()                               : " + Test.class.getClassLoader());
    System.out.println("ClassLoader.getSystemClassLoader()                        : " + ClassLoader.getSystemClassLoader());
    System.out.println("ClassLoader.getSystemClassLoader().getParent()            : " + ClassLoader.getSystemClassLoader().getParent());
    System.out.println("ClassLoader.getSystemClassLoader().getParent().getParent(): " + ClassLoader.getSystemClassLoader().getParent().getParent());
    ClassLoader platformClassLoader = ClassLoader.getSystemClassLoader().getParent();
    System.out.println(platformClassLoader.getClass());
    URLClassLoader loader = new URLClassLoader(new URL[0], platformClassLoader);
    System.out.println("loader.loadClass('java.sql.Driver')                       : " + loader.loadClass("java.sql.Driver"));
  }
}

Java 8 输出:

java.version                                              : 1.8.0_382
Test.class.getClassLoader()                               : sun.misc.Launcher$AppClassLoader@4e0e2f2a
ClassLoader.getSystemClassLoader()                        : sun.misc.Launcher$AppClassLoader@4e0e2f2a
ClassLoader.getSystemClassLoader().getParent()            : sun.misc.Launcher$ExtClassLoader@2a139a55
ClassLoader.getSystemClassLoader().getParent().getParent(): null
class sun.misc.Launcher$ExtClassLoader
loader.loadClass('java.sql.Driver')                       : interface java.sql.Driver

Java 17 输出:

java.version                                              : 17.0.8
Test.class.getClassLoader()                               : jdk.internal.loader.ClassLoaders$AppClassLoader@659e0bfd
ClassLoader.getSystemClassLoader()                        : jdk.internal.loader.ClassLoaders$AppClassLoader@659e0bfd
ClassLoader.getSystemClassLoader().getParent()            : jdk.internal.loader.ClassLoaders$PlatformClassLoader@3fee733d
ClassLoader.getSystemClassLoader().getParent().getParent(): null
class jdk.internal.loader.ClassLoaders$PlatformClassLoader
loader.loadClass('java.sql.Driver')                       : interface java.sql.Driver
© www.soinside.com 2019 - 2024. All rights reserved.