There is a problem with the initialization order of the default file system and the system class loader when both are custom and are specified via their respective system properties (-Djava.system.class.loader=... -Djava.nio.file.spi.DefaultFileSystemProvider=...).
To reproduce, I modified a test from the git repo test/jdk/java/lang/ClassLoader/CustomSystemLoader, slightly modified and reduced for clarity:
$ cat CustomLoader.java
import java.io.PrintStream;
import java.nio.file.Path;
public class CustomLoader extends ClassLoader {
private static PrintStream out = System.out;
public static ClassLoader INSTANCE;
public CustomLoader(ClassLoader classLoader) {
super("CustomSystemLoader", classLoader);
assert INSTANCE == null;
INSTANCE = this;
System.out.println("ROOT directory: " + Path.of("/")); // causes an exception
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
out.println("CustomLoader: loading class: " + name);
return super.loadClass(name);
}
}
$ cat InitSystemLoaderTest.java
public class InitSystemLoaderTest {
public static void main(String... args) {
// check that system class loader is the custom loader
ClassLoader loader = ClassLoader.getSystemClassLoader();
if (loader != CustomLoader.INSTANCE) {
throw new RuntimeException("Expected custom loader: "
+ CustomLoader.INSTANCE + " got: " + loader);
}
}
}
$ javac CustomLoader.java InitSystemLoaderTest.java
$ java -Djava.system.class.loader=CustomLoader -Djava.nio.file.spi.DefaultFileSystemProvider=CustomLoader InitSystemLoaderTest
NOTE that CustomLoader is definitely NOT a file system provider, but for the purpose of this demo, any class will do. The test fails before the custom file system provider gets instantiated.
The output looks like this:
Error occurred during initialization of VM
java.lang.Error: java.lang.IllegalStateException: getSystemClassLoader cannot be called during the system class loader instantiation
at java.nio.file.FileSystems$DefaultFileSystemHolder.getDefaultProvider(java.base@21.0.5/FileSystems.java:134)
at java.nio.file.FileSystems$DefaultFileSystemHolder$1.run(java.base@21.0.5/FileSystems.java:103)
at java.nio.file.FileSystems$DefaultFileSystemHolder$1.run(java.base@21.0.5/FileSystems.java:101)
at java.security.AccessController.doPrivileged(java.base@21.0.5/AccessController.java:319)
at java.nio.file.FileSystems$DefaultFileSystemHolder.defaultFileSystem(java.base@21.0.5/FileSystems.java:101)
at java.nio.file.FileSystems$DefaultFileSystemHolder.<clinit>(java.base@21.0.5/FileSystems.java:94)
at java.nio.file.FileSystems.getDefault(java.base@21.0.5/FileSystems.java:183)
at java.nio.file.Path.of(java.base@21.0.5/Path.java:148)
at CustomLoader.<init>(CustomLoader.java:12)
at jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(java.base@21.0.5/DirectConstructorHandleAccessor.java:62)
at java.lang.reflect.Constructor.newInstanceWithCaller(java.base@21.0.5/Constructor.java:502)
at java.lang.reflect.Constructor.newInstance(java.base@21.0.5/Constructor.java:486)
at java.lang.ClassLoader.initSystemClassLoader(java.base@21.0.5/ClassLoader.java:2012)
at java.lang.System.initPhase3(java.base@21.0.5/System.java:2333)
Caused by: java.lang.IllegalStateException: getSystemClassLoader cannot be called during the system class loader instantiation
at java.lang.ClassLoader.getSystemClassLoader(java.base@21.0.5/ClassLoader.java:1965)
at java.nio.file.FileSystems$DefaultFileSystemHolder.getDefaultProvider(java.base@21.0.5/FileSystems.java:124)
at java.nio.file.FileSystems$DefaultFileSystemHolder$1.run(java.base@21.0.5/FileSystems.java:103)
at java.nio.file.FileSystems$DefaultFileSystemHolder$1.run(java.base@21.0.5/FileSystems.java:101)
at java.security.AccessController.doPrivileged(java.base@21.0.5/AccessController.java:319)
at java.nio.file.FileSystems$DefaultFileSystemHolder.defaultFileSystem(java.base@21.0.5/FileSystems.java:101)
at java.nio.file.FileSystems$DefaultFileSystemHolder.<clinit>(java.base@21.0.5/FileSystems.java:94)
at java.nio.file.FileSystems.getDefault(java.base@21.0.5/FileSystems.java:183)
at java.nio.file.Path.of(java.base@21.0.5/Path.java:148)
at CustomLoader.<init>(CustomLoader.java:12)
at jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(java.base@21.0.5/DirectConstructorHandleAccessor.java:62)
at java.lang.reflect.Constructor.newInstanceWithCaller(java.base@21.0.5/Constructor.java:502)
at java.lang.reflect.Constructor.newInstance(java.base@21.0.5/Constructor.java:486)
at java.lang.ClassLoader.initSystemClassLoader(java.base@21.0.5/ClassLoader.java:2012)
at java.lang.System.initPhase3(java.base@21.0.5/System.java:2333)
Notice the actual source of the exceptions is Path.of() called at CustomLoader.java:12.
To reproduce, I modified a test from the git repo test/jdk/java/lang/ClassLoader/CustomSystemLoader, slightly modified and reduced for clarity:
$ cat CustomLoader.java
import java.io.PrintStream;
import java.nio.file.Path;
public class CustomLoader extends ClassLoader {
private static PrintStream out = System.out;
public static ClassLoader INSTANCE;
public CustomLoader(ClassLoader classLoader) {
super("CustomSystemLoader", classLoader);
assert INSTANCE == null;
INSTANCE = this;
System.out.println("ROOT directory: " + Path.of("/")); // causes an exception
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
out.println("CustomLoader: loading class: " + name);
return super.loadClass(name);
}
}
$ cat InitSystemLoaderTest.java
public class InitSystemLoaderTest {
public static void main(String... args) {
// check that system class loader is the custom loader
ClassLoader loader = ClassLoader.getSystemClassLoader();
if (loader != CustomLoader.INSTANCE) {
throw new RuntimeException("Expected custom loader: "
+ CustomLoader.INSTANCE + " got: " + loader);
}
}
}
$ javac CustomLoader.java InitSystemLoaderTest.java
$ java -Djava.system.class.loader=CustomLoader -Djava.nio.file.spi.DefaultFileSystemProvider=CustomLoader InitSystemLoaderTest
NOTE that CustomLoader is definitely NOT a file system provider, but for the purpose of this demo, any class will do. The test fails before the custom file system provider gets instantiated.
The output looks like this:
Error occurred during initialization of VM
java.lang.Error: java.lang.IllegalStateException: getSystemClassLoader cannot be called during the system class loader instantiation
at java.nio.file.FileSystems$DefaultFileSystemHolder.getDefaultProvider(java.base@21.0.5/FileSystems.java:134)
at java.nio.file.FileSystems$DefaultFileSystemHolder$1.run(java.base@21.0.5/FileSystems.java:103)
at java.nio.file.FileSystems$DefaultFileSystemHolder$1.run(java.base@21.0.5/FileSystems.java:101)
at java.security.AccessController.doPrivileged(java.base@21.0.5/AccessController.java:319)
at java.nio.file.FileSystems$DefaultFileSystemHolder.defaultFileSystem(java.base@21.0.5/FileSystems.java:101)
at java.nio.file.FileSystems$DefaultFileSystemHolder.<clinit>(java.base@21.0.5/FileSystems.java:94)
at java.nio.file.FileSystems.getDefault(java.base@21.0.5/FileSystems.java:183)
at java.nio.file.Path.of(java.base@21.0.5/Path.java:148)
at CustomLoader.<init>(CustomLoader.java:12)
at jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(java.base@21.0.5/DirectConstructorHandleAccessor.java:62)
at java.lang.reflect.Constructor.newInstanceWithCaller(java.base@21.0.5/Constructor.java:502)
at java.lang.reflect.Constructor.newInstance(java.base@21.0.5/Constructor.java:486)
at java.lang.ClassLoader.initSystemClassLoader(java.base@21.0.5/ClassLoader.java:2012)
at java.lang.System.initPhase3(java.base@21.0.5/System.java:2333)
Caused by: java.lang.IllegalStateException: getSystemClassLoader cannot be called during the system class loader instantiation
at java.lang.ClassLoader.getSystemClassLoader(java.base@21.0.5/ClassLoader.java:1965)
at java.nio.file.FileSystems$DefaultFileSystemHolder.getDefaultProvider(java.base@21.0.5/FileSystems.java:124)
at java.nio.file.FileSystems$DefaultFileSystemHolder$1.run(java.base@21.0.5/FileSystems.java:103)
at java.nio.file.FileSystems$DefaultFileSystemHolder$1.run(java.base@21.0.5/FileSystems.java:101)
at java.security.AccessController.doPrivileged(java.base@21.0.5/AccessController.java:319)
at java.nio.file.FileSystems$DefaultFileSystemHolder.defaultFileSystem(java.base@21.0.5/FileSystems.java:101)
at java.nio.file.FileSystems$DefaultFileSystemHolder.<clinit>(java.base@21.0.5/FileSystems.java:94)
at java.nio.file.FileSystems.getDefault(java.base@21.0.5/FileSystems.java:183)
at java.nio.file.Path.of(java.base@21.0.5/Path.java:148)
at CustomLoader.<init>(CustomLoader.java:12)
at jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(java.base@21.0.5/DirectConstructorHandleAccessor.java:62)
at java.lang.reflect.Constructor.newInstanceWithCaller(java.base@21.0.5/Constructor.java:502)
at java.lang.reflect.Constructor.newInstance(java.base@21.0.5/Constructor.java:486)
at java.lang.ClassLoader.initSystemClassLoader(java.base@21.0.5/ClassLoader.java:2012)
at java.lang.System.initPhase3(java.base@21.0.5/System.java:2333)
Notice the actual source of the exceptions is Path.of() called at CustomLoader.java:12.
- csr for
-
JDK-8346709 Can't use custom default file system provider with custom system class loader
-
- Closed
-
- links to
-
Commit(master) openjdk/jdk/f1196638
-
Review(master) openjdk/jdk/22842