Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8346573

Can't use custom default file system provider with custom system class loader

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P3 P3
    • 25
    • 8, 17, 21
    • core-libs
    • None
    • b05
    • generic
    • generic

      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.

            alanb Alan Bateman
            mkartashev Maxim Kartashev
            Votes:
            1 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: