Changing the default file system provider is broken :(

Peter Levart peter.levart at gmail.com
Sat Apr 22 19:47:03 UTC 2017



On 04/22/2017 08:10 PM, forax at univ-mlv.fr wrote:
> Hi Peter
>
>     Hi Remi,
>
>     On 04/22/2017 01:20 PM, Remi Forax wrote:
>
>         Ooops !
>         if you use the module path, you can not change the default system provider mechanism anymore,
>         mostly because the module implementation internally uses java.nio.file.Path at different places.
>
>         First, trying to initialize the default system provider in Java code do not work at all,
>         calling
>            System.setProperty("java.nio.file.spi.DefaultFileSystemProvider", "...");
>         in a main does nothing because the jigsaw implementation has already loaded the default implementation to be able to inspect the modules.
>
>         Then, if you try to use the command line
>           -Djava.nio.file.spi.DefaultFileSystemProvider=...
>         you have various bootstrapping issues.
>
>         With exploded modules, when trying to initialize the default file system, the part of jigsaw that reads exploded modules uses path.toFile() that fails it checks that the path belongs to the default file system which is not already initialized
>         (see below for the whole stacktrace)
>
>         With modular jars, when trying to initialize the default file system, the JarModuleReader also uses path.toFile(), leading to the same error
>
>         One way to solve that is to change the code in FileSystems.getDefault() to add a nullcheck,
>                  FileSystem defaultFileSystem = DefaultFileSystemHolder.defaultFileSystem;
>                  if (jdk.internal.misc.VM.isBooted() && defaultFileSystem != null) {
>                      return defaultFileSystem;
>                  } else {
>                      return BuiltinFileSystemHolder.builtinFileSystem;
>                  }
>         Another solution is to change the code of jigsaw to only use the builtinFileSystem, delaying the initialization of the default system which will also solve the case where an application uses System.setProperty.
>
>
>     I think the problem is that what FileSystems.getDefault() returns,
>     changes over time. So you have Path instances associated with
>     "builtin" filesystem, constructed before VM.isBooted() and after
>     it is booted, Path instances are associated with what is
>     configured to be the "default" filesystem. If those two differ and
>     an instance, constructed before VM.isBooted() lives past the boot
>     time and then .toFile() is called on such instance, we get
>     "UnsupportedOperationException: Path not associated with default
>     file system"...
>
>     Maybe Alan could shed some light into this. As part of jigsaw
>     implementation, the FileSystems.getDefault() was changed from:
>
>         public static FileSystem getDefault() {
>             return DefaultFileSystemHolder.defaultFileSystem;
>         }
>
>     to:
>
>         public static FileSystem getDefault() {
>             if (jdk.internal.misc.VM.isBooted()) {
>                 return DefaultFileSystemHolder.defaultFileSystem;
>             } else {
>                 return BuiltinFileSystemHolder.builtinFileSystem;
>             }
>         }
>
>     Probably because of early bootstrap issues. Module system needs
>     FileSystem and custom FileSystem classes can not be loaded at that
>     time yet.
>
>     So I think that your second solution would be the right one.
>     Jigsaw should only use the builtin filesystem explicitly,
>     refraining from initializing the default filesystem. And
>     Path.toFile() should allow creating a File from a Path in either
>     case: whether Path is associated with builtin or default filesystem.
>
>
> I think your right for the modular jars case, ModulePath store an 
> array of Path created before the VM is considered as booted and 
> consume them lazily :(
> I believe that replacing the path.toFile() by new 
> File(path.toString()) will fix this issue.

Or this might work too:

http://cr.openjdk.java.net/~plevart/jdk9-dev/Path.toFile/webrev.01/

A variant of this might be for FileSystems.getDefault() to start 
returning the custom default filesystem as soon as initLevel reaches 2 
(after module system is initialized). This might allow custom default 
file system to be effective even before the VM is fully booted (for 
custom security manager or system class loader or java agent to already 
take advantage of it). But that probably would mean that the custom 
default filesystem loading logic would have to be modified in order to 
cope with system class loader not being setup already - it could use the 
builtin app class loader for locating and loading the classes...

Do you happen to have a custom default filesystem to try this with?

Regards, Peter

>
>
>     Regards, Peter
>
>
> Rémi
>
>
>         cheers,
>         Rémi
>
>
>         Stacktrace with exploded modules:
>         Error: A JNI error has occurred, please check your installation and try again
>         Exception in thread "main" java.lang.Error: java.lang.UnsupportedOperationException: Path not associated with default file system.
>         	at java.base/java.nio.file.FileSystems$DefaultFileSystemHolder.getDefaultProvider(FileSystems.java:139)
>         	at java.base/java.nio.file.FileSystems$DefaultFileSystemHolder.access$100(FileSystems.java:100)
>         	at java.base/java.nio.file.FileSystems$DefaultFileSystemHolder$1.run(FileSystems.java:109)
>         	at java.base/java.nio.file.FileSystems$DefaultFileSystemHolder$1.run(FileSystems.java:107)
>         	at java.base/java.security.AccessController.doPrivileged(Native Method)
>         	at java.base/java.nio.file.FileSystems$DefaultFileSystemHolder.defaultFileSystem(FileSystems.java:107)
>         	at java.base/java.nio.file.FileSystems$DefaultFileSystemHolder.<clinit>(FileSystems.java:101)
>         	at java.base/java.nio.file.FileSystems.getDefault(FileSystems.java:188)
>         	at java.base/java.nio.file.Path.toFile(Path.java:655)
>         	at java.base/jdk.internal.module.ModuleReferences$JarModuleReader.newJarFile(ModuleReferences.java:229)
>         	at java.base/jdk.internal.module.ModuleReferences$JarModuleReader.<init>(ModuleReferences.java:239)
>         	at java.base/jdk.internal.module.ModuleReferences.lambda$newJarModule$0(ModuleReferences.java:96)
>         	at java.base/jdk.internal.module.ModuleReferenceImpl.open(ModuleReferenceImpl.java:88)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.createModuleReader(BuiltinClassLoader.java:953)
>         	at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1719)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.moduleReaderFor(BuiltinClassLoader.java:945)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:702)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(BuiltinClassLoader.java:651)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.findClass(BuiltinClassLoader.java:532)
>         	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:585)
>         	at java.base/java.lang.Class.forName(Class.java:447)
>         	at java.base/sun.launcher.LauncherHelper.loadModuleMainClass(LauncherHelper.java:585)
>         	at java.base/sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:523)
>         Caused by: java.lang.UnsupportedOperationException: Path not associated with default file system.
>         	at java.base/java.nio.file.Path.toFile(Path.java:658)
>         	at java.base/jdk.internal.module.ModuleReferences$JarModuleReader.newJarFile(ModuleReferences.java:229)
>         	at java.base/jdk.internal.module.ModuleReferences$JarModuleReader.<init>(ModuleReferences.java:239)
>         	at java.base/jdk.internal.module.ModuleReferences.lambda$newJarModule$0(ModuleReferences.java:96)
>         	at java.base/jdk.internal.module.ModuleReferenceImpl.open(ModuleReferenceImpl.java:88)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.createModuleReader(BuiltinClassLoader.java:953)
>         	at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1719)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.moduleReaderFor(BuiltinClassLoader.java:945)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:702)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(BuiltinClassLoader.java:651)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:576)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:550)
>         	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185)
>         	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:473)
>         	at java.base/java.lang.Class.forName0(Native Method)
>         	at java.base/java.lang.Class.forName(Class.java:374)
>         	at java.base/java.nio.file.FileSystems$DefaultFileSystemHolder.getDefaultProvider(FileSystems.java:129)
>         	... 22 more
>
>
>         StackTrace with modular jars:
>         Error: A JNI error has occurred, please check your installation and try again
>         Exception in thread "main" java.lang.Error: java.lang.UnsupportedOperationException: Path not associated with default file system.
>         	at java.base/java.nio.file.FileSystems$DefaultFileSystemHolder.getDefaultProvider(FileSystems.java:139)
>         	at java.base/java.nio.file.FileSystems$DefaultFileSystemHolder.access$100(FileSystems.java:100)
>         	at java.base/java.nio.file.FileSystems$DefaultFileSystemHolder$1.run(FileSystems.java:109)
>         	at java.base/java.nio.file.FileSystems$DefaultFileSystemHolder$1.run(FileSystems.java:107)
>         	at java.base/java.security.AccessController.doPrivileged(Native Method)
>         	at java.base/java.nio.file.FileSystems$DefaultFileSystemHolder.defaultFileSystem(FileSystems.java:107)
>         	at java.base/java.nio.file.FileSystems$DefaultFileSystemHolder.<clinit>(FileSystems.java:101)
>         	at java.base/java.nio.file.FileSystems.getDefault(FileSystems.java:188)
>         	at java.base/java.nio.file.Path.toFile(Path.java:655)
>         	at java.base/jdk.internal.module.ModuleReferences$JarModuleReader.newJarFile(ModuleReferences.java:229)
>         	at java.base/jdk.internal.module.ModuleReferences$JarModuleReader.<init>(ModuleReferences.java:239)
>         	at java.base/jdk.internal.module.ModuleReferences.lambda$newJarModule$0(ModuleReferences.java:96)
>         	at java.base/jdk.internal.module.ModuleReferenceImpl.open(ModuleReferenceImpl.java:88)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.createModuleReader(BuiltinClassLoader.java:953)
>         	at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1719)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.moduleReaderFor(BuiltinClassLoader.java:945)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:702)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(BuiltinClassLoader.java:651)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.findClass(BuiltinClassLoader.java:532)
>         	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:585)
>         	at java.base/java.lang.Class.forName(Class.java:447)
>         	at java.base/sun.launcher.LauncherHelper.loadModuleMainClass(LauncherHelper.java:585)
>         	at java.base/sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:523)
>         Caused by: java.lang.UnsupportedOperationException: Path not associated with default file system.
>         	at java.base/java.nio.file.Path.toFile(Path.java:658)
>         	at java.base/jdk.internal.module.ModuleReferences$JarModuleReader.newJarFile(ModuleReferences.java:229)
>         	at java.base/jdk.internal.module.ModuleReferences$JarModuleReader.<init>(ModuleReferences.java:239)
>         	at java.base/jdk.internal.module.ModuleReferences.lambda$newJarModule$0(ModuleReferences.java:96)
>         	at java.base/jdk.internal.module.ModuleReferenceImpl.open(ModuleReferenceImpl.java:88)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.createModuleReader(BuiltinClassLoader.java:953)
>         	at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1719)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.moduleReaderFor(BuiltinClassLoader.java:945)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:702)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(BuiltinClassLoader.java:651)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:576)
>         	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:550)
>         	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185)
>         	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:473)
>         	at java.base/java.lang.Class.forName0(Native Method)
>         	at java.base/java.lang.Class.forName(Class.java:374)
>         	at java.base/java.nio.file.FileSystems$DefaultFileSystemHolder.getDefaultProvider(FileSystems.java:129)
>         	... 22 more
>
>
>



More information about the jigsaw-dev mailing list