Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8357249

Compiler task keeps --system files open

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P4 P4
    • 26
    • 25
    • tools
    • 9
    • generic
    • generic

      When used with the `--system` option pointing to a different modularized JDK, `JavacTask` keeps `lib/jrt-fs.jar` and `lib/modules` open even after it is done. This is particularly problematic on Windows, where this makes it (temporarily) impossible to delete the files.

      This is a problem for long-lived worker processes that respond to multiple compilation requests and receive the inputs, including the system JDK, in per-request directories that are cleaned up after compilation. This use case arises in the context of the build system Bazel.

      For `jrt-fs.jar`, the reason is that the `URLClassLoader` that loads the `JrtFileSystemProvider` from it is never closed. This can be fixed in the host JDK by closing the class loader when the corresponding `JrtFileSystem` is closed.

      For `modules`, the situation is more difficult: it is kept open as a result of a `FileChannel#map` call in `BasicImageReader`. Closing it explicitly appears to require `Unsafe#invokeCleaner` as well as reflection when done from the host JDK (see JDK-4724038).

      Run the following program on Linux or macOS with the path to another JDK as its only argument to reproduce the issue:

      ```
      import java.io.BufferedReader;
      import java.io.IOException;
      import java.io.InputStreamReader;
      import java.net.URI;
      import java.util.List;
      import javax.tools.JavaFileObject;
      import javax.tools.SimpleJavaFileObject;
      import javax.tools.ToolProvider;class Scratch {
        public static void main(String[] args) throws IOException, InterruptedException {
          var compiler = ToolProvider.getSystemJavaCompiler();
          var compilationUnit =
              new SimpleJavaFileObject(URI.create("string:///Test.java"), JavaFileObject.Kind.SOURCE) {
                @Override
                public CharSequence getCharContent(boolean ignoreEncodingErrors) {
                  return """
                     public class Test {
                          public static void main(String[] args) {
                              System.out.println("Hello, World!");
                          }
                     }
                     """;
                }
              };
          try (var fileManager = compiler.getStandardFileManager(null, null, null)) {
            compiler
                .getTask(
                    null, fileManager, null, List.of("--system", args[0]), null, List.of(compilationUnit))
                .call();
          }    var process =
              new ProcessBuilder()
                  .command("lsof", "-p", String.valueOf(ProcessHandle.current().pid()))
                  .redirectOutput(ProcessBuilder.Redirect.PIPE)
                  .redirectError(ProcessBuilder.Redirect.INHERIT)
                  .start();
          try (var stdout = process.getInputStream();
              var reader = new BufferedReader(new InputStreamReader(stdout))) {
            reader.lines().filter(line -> line.contains(args[0])).forEach(System.out::println);
          }
          process.waitFor();
        }
      }
      ```

            henryjen Henry Jen
            fmeum Fabian Meumertzheim
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated: