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

(jrtfs) ThreadLocal memory leak in ImageBufferCache when using jrtfs

    XMLWordPrintable

    Details

    • Subcomponent:
    • Resolved In Build:
      b21
    • Verification:
      Verified

      Description

      ADDITIONAL SYSTEM INFORMATION :
      All system.

      A DESCRIPTION OF THE PROBLEM :
      ImageBufferCache has a static ThreadLocal field which is never released.

      When loading from jrt-fs.jar, a strong reference to `ImageBufferCache$BufferReference` (loaded by a separate `JrtFileSystemProvider$JrtFsLoader`) will be kept
      in Metaspace forever, because `jrt-fs.jar` contains a copy of `ImageBufferCache$BufferReference` class.

      The intention was to make BufferReference a WeakReference, but unfortunately, BufferReference.class itself is a strong reference that prevents `JrtFileSystemProvider$JrtFsLoader` from being GCed.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      ```
      import java.io.IOException;
      import java.net.URI;
      import java.nio.file.DirectoryStream;
      import java.nio.file.FileSystem;
      import java.nio.file.FileSystems;
      import java.nio.file.Files;
      import java.nio.file.Path;
      import java.util.HashMap;
      import java.util.Map;

      public class Test {
          public static void main(String[] args) throws IOException, ClassNotFoundException {
              Map<String, String> map = new HashMap<>();
              map.put("java.home", System.getProperty("java.home"));
              for (int i = 0; i < 1000; ++i) {
                  try (FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), map)) {
                      Path path = fs.getPath("modules");
                      try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
                          stream.forEach(it -> {
                          });
                      }
                  }
              }
          }
      }
      ```

      Then run `javac Test.java && java -Xmx32m -XX:MaxMetaspaceSize=32m Test` you will get `OOM: Metaspace`.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The reproducer code should be able to run.
      ACTUAL -
      OOM: Metaspace

      ---------- BEGIN SOURCE ----------
      import java.io.IOException;
      import java.net.URI;
      import java.nio.file.DirectoryStream;
      import java.nio.file.FileSystem;
      import java.nio.file.FileSystems;
      import java.nio.file.Files;
      import java.nio.file.Path;
      import java.util.HashMap;
      import java.util.Map;

      public class Test {
          public static void main(String[] args) throws IOException, ClassNotFoundException {
              Map<String, String> map = new HashMap<>();
              map.put("java.home", System.getProperty("java.home"));
              for (int i = 0; i < 1000; ++i) {
                  try (FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), map)) {
                      Path path = fs.getPath("modules");
                      try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
                          stream.forEach(it -> {
                          });
                      }
                  }
              }
          }
      }
      ---------- END SOURCE ----------

      FREQUENCY : always


        Attachments

          Issue Links

            Activity

              People

              Assignee:
              sundar Sundararajan Athijegannathan
              Reporter:
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: