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