RFR: 8331467: ImageReaderFactory can cause a ClassNotFoundException if the default FileSystemProvider is not the system-default provider

Alan Bateman alanb at openjdk.org
Sun Nov 10 17:07:36 UTC 2024


On Sun, 10 Nov 2024 14:48:26 GMT, jyxzwd <duke at openjdk.org> wrote:

>> I got it.Thank you for the detailed explanation!Maybe we should consider another way to load the custom FileSystemProvider.
>
> If we load the custom DefaultFileSystemProvider by SystemClassLoader,then we will step into the method SystemModuleFinders$SystemModuleReader#findImageLocation again, and the var imageReader will be null.But we can not define a custom classLoader to load the custom DefaultFileSystemProvider since it needs to maintain JDK 8 source compatibility.So the only way that I can think of is to use the installedProvider which has the 'file' scheme to directly get the 'modules' path value.
> 
> In ImageReaderFactory:
> 
> private static final Path BOOT_MODULES_JIMAGE = null;
> 
>     static {
>         // check installed providers
>         for (FileSystemProvider provider : FileSystemProvider.installedProviders()) {
>             if ("file".equalsIgnoreCase(provider.getScheme())) {
>                 try {
>                     BOOT_MODULES_JIMAGE = provider.getFileSystem(URI.create("file:/")).getPath(JAVA_HOME, "lib", "modules");
>                     if (BOOT_MODULES_JIMAGE != null) break;
>                 } catch (UnsupportedOperationException uoe) {
>                 }
>             }
>         }
>     }
> 
> What do you think of this?I am new to openjdk source development.So I truely appreciate the time you dedecate to my question!

I assume this will lead to recursive initialisation, e.g. `FileSystems.getFileSystem(URI.create("jrt:/"))` will use FileSystemProvider.installedProviders to iterate over the installed providers.

I don't have time to look into this more but I think it will have to reflectively get the FileSystem so that the code isn't compiled with references to the built-in provider, as in something like this (not tested):


    private static final Path BOOT_MODULES_JIMAGE;
    static {
        FileSystem fs;
        if (ImageReaderFactory.class.getClassLoader() == null) {
            // fs = DefaultFileSystemProvider.theFileSystem()
            try {
                fs = (FileSystem) Class.forName("sun.nio.fs.DefaultFileSystemProvider")
                        .getMethod("theFileSystem")
                        .invoke(null);
            } catch (Exception e) {
                throw new ExceptionInInitializerError(e);
            }
        } else {
            fs = FileSystems.getDefault();
        }
        BOOT_MODULES_JIMAGE = fs.getPath(JAVA_HOME, "lib", "modules");
    }

Also just to say that we need to create a good test for this issue. I expect it will be rarely to interpose on the default file system and use jrtfs at the same time, but that is what this bug report is about so we'll need to create a good test.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/21997#discussion_r1835741459


More information about the core-libs-dev mailing list