Discussion:
Changing the default file system provider is broken :(
Remi Forax
2017-04-22 11:20:15 UTC
Permalink
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.

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
Peter Levart
2017-04-22 15:14:32 UTC
Permalink
Hi Remi,
Post by Remi Forax
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.

Regards, Peter
Post by Remi Forax
cheers,
Rémi
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
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
f***@univ-mlv.fr
2017-04-22 18:10:48 UTC
Permalink
Hi Peter
Post by Peter Levart
Hi Remi,
Post by Remi Forax
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,
public static FileSystem getDefault() {
return DefaultFileSystemHolder.defaultFileSystem;
}
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.
Post by Peter Levart
Regards, Peter
Rémi
Post by Peter Levart
Post by Remi Forax
cheers,
Rémi
Error: A JNI error has occurred, please check your installation and try again
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
Error: A JNI error has occurred, please check your installation and try again
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
Peter Levart
2017-04-22 19:47:03 UTC
Permalink
Post by f***@univ-mlv.fr
Hi Peter
Hi Remi,
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
public static FileSystem getDefault() {
return DefaultFileSystemHolder.defaultFileSystem;
}
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
Post by f***@univ-mlv.fr
Regards, Peter
Rémi
cheers,
Rémi
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
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
f***@univ-mlv.fr
2017-04-22 20:06:41 UTC
Permalink
[...]
Post by Peter Levart
http://cr.openjdk.java.net/~plevart/jdk9-dev/Path.toFile/webrev.01/
yes, it's better
Post by Peter Levart
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?
sure, a dummy one that delegates everything to the builtin
https://gist.github.com/forax/615828b41c33eccda33afdf2eba1db87
Post by Peter Levart
Regards, Peter
regards,
Rémi
Peter Levart
2017-04-22 20:48:43 UTC
Permalink
Post by Peter Levart
http://cr.openjdk.java.net/~plevart/jdk9-dev/Path.toFile/webrev.01/
yes, it's better
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?
sure, a dummy one that delegates everything to the builtin
https://gist.github.com/forax/615828b41c33eccda33afdf2eba1db87
Well, it works at least when
-Djava.nio.file.spi.DefaultFileSystemProvider=... is specified on the
command line. But when the system property is set as 1st thing in main()
method, it is already too late. It seems that after boot sequence is
finished (VM.isBooted() == true)and before main() method is called, some
code needs the FileSystem again, so default file system is already
initialized before the main() is executed.

Perhaps there needs to be another initLevel which would be set just
before the invocation of the main() method?

Regards, Peter
Alan Bateman
2017-04-23 10:38:21 UTC
Permalink
Post by Peter Levart
Well, it works at least when
-Djava.nio.file.spi.DefaultFileSystemProvider=... is specified on the
command line. But when the system property is set as 1st thing in
main() method, it is already too late. It seems that after boot
sequence is finished (VM.isBooted() == true)and before main() method
is called, some code needs the FileSystem again, so default file
system is already initialized before the main() is executed.
Perhaps there needs to be another initLevel which would be set just
before the invocation of the main() method?
I don't think we go there as there are just too many scenarios where
"user code" can execute before the application main method. Instead, I
think this is a case where the default file system provider can only be
overridden by setting the property on the command line.

-Alan
Remi Forax
2017-04-23 18:28:38 UTC
Permalink
----- Mail original -----
Envoyé: Dimanche 23 Avril 2017 12:38:21
Objet: Re: Changing the default file system provider is broken :(
Post by Peter Levart
Well, it works at least when
-Djava.nio.file.spi.DefaultFileSystemProvider=... is specified on the
command line. But when the system property is set as 1st thing in
main() method, it is already too late. It seems that after boot
sequence is finished (VM.isBooted() == true)and before main() method
is called, some code needs the FileSystem again, so default file
system is already initialized before the main() is executed.
Perhaps there needs to be another initLevel which would be set just
before the invocation of the main() method?
I don't think we go there as there are just too many scenarios where
"user code" can execute before the application main method. Instead, I
think this is a case where the default file system provider can only be
overridden by setting the property on the command line.
This should be added to the compatibility list because mocking the FileSystem for testing purpose is common, at least in my own bubble.
-Alan
Rémi
Alan Bateman
2017-04-24 08:05:49 UTC
Permalink
Post by Remi Forax
This should be added to the compatibility list because mocking the FileSystem for testing purpose is common, at least in my own bubble.
I would prefer not introduce compatibility issues in this area if
possible. I think the best we can do is read the
java.nio.file.spi.DefaultFileSystemProvider property on first usage
after the module system is initialized.

So assume you set the property in your main method:

1. If an agent is started before your main, and the agent uses the file
system API in its initialization, then the built-in provider will be
used. This is the same as JDK 7 and JDK 8.

2. If a custom system class loader or a custom security manager is
configuration, and if the initialization of either uses the file system
API, then the built-in provider will be used. This is the same as JDK 7
and JDK 8.

If set on the command line:

(a) If an agent uses the file system API then it will use the custom
provider. This is the same as JDK 7 and JDK 8.

(b) If a custom system class loader or a custom security manager
attempts to use the file system API then it will fail with a recursive
initialization error or exception (it varies). This is because the
custom file system provider is located using the system class loader.
This is the same as JDK 7 and JDK 8 although the exception/error is
different as this area has been cleared up a lot in JDK 9.

We could improve (b) by changing the spec to allow custom file system
providers be located before the system class loader is initialized but
it hardly seems worth it.

Do you agree with this? If so then we can get the implementation aligned
and create some issues in JIRA to ensure that we have tests to cover all
these scenarios.

-Alan

Alan Bateman
2017-04-22 20:37:50 UTC
Permalink
Post by Peter Levart
http://cr.openjdk.java.net/~plevart/jdk9-dev/Path.toFile/webrev.01/
Only partly as there is also the issue of resolving paths associated
with one provider against a path associated with another.
Post by Peter Levart
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).
When running with a custom file system provider then it's important that
objects associated with the built-in provider don't leak to user code.
So yes, getDefault() should return the custom file system after the
module system is initialized so that custom system class loaders, custom
security manager, and agents get objects associated with the custom
provider.

-Alan
Peter Levart
2017-04-22 21:03:43 UTC
Permalink
Hi Alan,
Post by Alan Bateman
Post by Peter Levart
http://cr.openjdk.java.net/~plevart/jdk9-dev/Path.toFile/webrev.01/
Only partly as there is also the issue of resolving paths associated
with one provider against a path associated with another.
So module system would need to keep using the builtin filesystem for any
Path manipulation after VM.isBooted. At least within the boot Layer.

There's no public API in module system that would return Path objects to
user, is it?
Post by Alan Bateman
Post by Peter Levart
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).
When running with a custom file system provider then it's important
that objects associated with the built-in provider don't leak to user
code. So yes, getDefault() should return the custom file system after
the module system is initialized so that custom system class loaders,
custom security manager, and agents get objects associated with the
custom provider.
-Alan
Right. No user code should see builtin Path(s) when custom default file
system is configured.

Regards, Peter
Alan Bateman
2017-04-22 20:26:59 UTC
Permalink
Post by Remi Forax
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.
Sigh, this is a bug here. A custom default file system can't be used
during early startup so this is why the module system uses the built-in
implementation. The bug is that is should always derive paths and never
use Paths.get or toFile as that risks mixing paths from the built-in
file system provider with the custom provider. The patch to fix is
straight-forward and I'll get that in jake soon. The only change needed
in the file system code is that FileSystems.getDefault should use
VM.isModuleSystemInited() rather than is VM.booted() to allow for the
corner case that is a custom system class loader or custom security
manager using the file system API.

-Alan.
Loading...