On Mon, 8 Jun 2026 10:31:48 GMT, Dusan Balek <[email protected]> wrote:

> When used with the `--system` option to target a different modularized JDK, 
> `JavacTask` keeps both `lib/jrt-fs.jar` and `lib/modules` open even after it 
> completes.
> 
> The `lib/jrt-fs.jar` file remains open because the host-side 
> `JrtFileSystemProvider` creates a `URLClassLoader` to load the target 
> platform's `JrtFileSystemProvider` from `lib/jrt-fs.jar` when creating a 
> `JrtFileSystem`. This `URLClassLoader` is never closed, causing the file to 
> remain open.
> 
> The `lib/modules` file remains open because `BasicImageReader` uses a 
> memory-mapped file whose mapping persists until the associated buffer is 
> garbage-collected.
> 
> To ensure that `lib/jrt-fs.jar` is properly closed, the proposed solution is 
> to make the client responsible for closing the file system's class loader 
> when "java.home" is passed in the `env` argument to 
> `FileSystems.newFileSystem(...)`.
> This approach (currently implemented in the `Locations` class) is simple and 
> works reliably even with older target platform versions. (An alternative 
> approach would be to automatically close the `URLClassLoader` when the 
> `JrtFileSystem` is closed. However, this solution has two significant 
> drawbacks. First, it does not work with older target platform versions 
> because it requires modifications to the target platform's `JrtFileSystem` 
> implementation. Second, it is not reliable. A user may obtain a reference to 
> the provider that created a `JrtFileSystem` instance, close that instance, 
> and then use the same provider to create another `JrtFileSystem`. In that 
> case, the provider's `URLClassLoader` may have already been closed 
> automatically, preventing the creation of the new file system instance).
> 
> To ensure that `lib/modules` is properly closed, the proposed solution is to 
> modify `BasicImageReader` so that it uses memory-mapped I/O only for the 
> current runtime and falls back to regular file I/O when accessing a different 
> target system. (An alternative solution would be to explicitly unmap the 
> memory-mapped file when the reader is closed. On JDK 22 and later, the 
> Foreign Function & Memory API could be used for that purpose. However, in 
> that case, `lib/jrt-fs.jar` could no longer be compiled to run on JDK 8). 
> Note that neither of these solutions work for older target platform versions, 
> as both require changes to the target platform's `BasicImageReader` 
> implementation.
> 
> 
> ---------
> - [x] I confirm that I make this contribution in accordance with the [OpenJDK 
> Interim AI Policy](https://openjdk.org/legal/ai).

test/langtools/tools/javac/SystemFilesClosed.java line 73:

> 71:         }
> 72:         Files.copy(jrtfsPath, target.resolve("jrt-fs.jar"), 
> StandardCopyOption.REPLACE_EXISTING);
> 73:         Files.copy(modulesPath, target.resolve("modules"), 
> StandardCopyOption.REPLACE_EXISTING);

Did you consider just invoking jlink to create a target image, e.g.

java.util.spi.ToolProvider.findFirst("jlink")
    .orElseThrow()
    .run(System.out, System.err, "--add-modules", "java.base", "--output", 
"testimage")

That would avoid the test needing to know/copy lib/modules and lib/jrt-fs.jar.

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

PR Review Comment: https://git.openjdk.org/jdk/pull/31417#discussion_r3375279340

Reply via email to