-1

This works with 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"));
  }
}

But throws ClassNotFoundException with Java 17:

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)

Great diagram explaining class loaders (Java 9+):

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

Related/similar issues:

1 Answer 1

-1

My current understanding is that if a null parent is used, really only the java base classes plus the classes in the URL[] parameter will be available.

If 'non-basic' classes from modules like 'java.sql' are also required, then at least the platform classloader needs to be used as parent.

ClassLoader.getPlatformClassLoader() is available since Java 9, as pointed out by @VGR.

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.getPlatformClassLoader()                      : " + ClassLoader.getPlatformClassLoader());
    URLClassLoader loader = new URLClassLoader(new URL[0], ClassLoader.getPlatformClassLoader());
    System.out.println("loader.loadClass('java.sql.Driver')                       : " + loader.loadClass("java.sql.Driver"));
  }
}

Output:

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@30f39991
ClassLoader.getPlatformClassLoader()                      : jdk.internal.loader.ClassLoaders$PlatformClassLoader@30f39991
loader.loadClass('java.sql.Driver')                       : interface java.sql.Driver
Sign up to request clarification or add additional context in comments.

3 Comments

ClassLoader.getSystemClassLoader().getParent() is an unreliable hack. Did you happen to try ClassLoader.getPlatformClassLoader() as the parent?
We still compile with Java 8, which is probably why I didn't see that method. But for modern Java this is definitely the way to go.
Or you use java.sql.Driver.class.getClassLoader() as the parent loader…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.