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

jyxzwd duke at openjdk.org
Sun Nov 10 14:51:14 UTC 2024


On Sun, 10 Nov 2024 04:50:36 GMT, jyxzwd <duke at openjdk.org> wrote:

>> The jrt file system provider supports both the current JDK and a remote/target JDK. When the JDK is not the current JDK then it loads the jrt file system provider from target's JDK jrt-fs.jar. To understand this more, try this example where you set targetJDK to the file path of another JDK on your system.
>> 
>> 
>> String targetJDK = .
>> var fs = FileSystems.newFileSystem(URI.create("jrt:/"), Map.of("java.home", targetJDK));
>> byte[] classBytes = Files.readAllBytes(fs.getPath("/modules/java.base/java/lang/String.class"));
>> 
>> 
>> Run with `-Xlog:class+load` and you'll see jrtfs and support jimage class files loaded from the target JDK. If you dig deeper you'll see they are loaded by a custom class loader, they are not defined by the boot loader and aren't in java.base. Hopefully this makes it clear why classes in jdk.internal.jimage or jdk.internal.jrtfs can't access JDK internal classes.
>
> 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!

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

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


More information about the core-libs-dev mailing list