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

(fs) More than one instance of built-in FileSystem observed in heap

    Details

    • Subcomponent:
    • Resolved In Build:
      b23

      Backports

        Description

        We have a local mod that needed access to the builtin FileSystem, and used
        sun.nio.fs.DefaultFileSystemProvider.create()
        as is done in FileSystems.java and FilePermissions.java
        and we ran into

        Caused by: java.lang.UnsupportedOperationException: Path not associated with default file system.
                at java.base/java.nio.file.Path.toFile(Path.java:771)

        and the root cause was that we had two instances of LinuxFileSystem, but much of nio code assumes there's exactly one instance of the default FileSystem. Here's a demo that stock jdk12 can end up with more than one LinuxFileSystem instance:

        If you run this program
        ----------
        public class Sleeper {
            public static void main(String[] args) throws Throwable {
                java.nio.file.FileSystems.getDefault();
                Runtime.getRuntime().exec(new String[] {"/bin/sleep", "120"}).waitFor();
            }
        }
        -----------
        and then $ jmap -histo 213201 | grep LinuxFileSystem
         216: 2 64 sun.nio.fs.LinuxFileSystem (java.base@12-ea)
         278: 2 32 sun.nio.fs.LinuxFileSystemProvider (java.base@12-ea)

        I took a look at FilePermission to see if I could identify a user-visible bug as a result of the duplicate instances, but came up empty. Nevertheless, it is probably intended to have only one - that helps with maintainer sanity and keep down startup overhead.

        ---

        It looks like the intent is to have only a single instance, but there is no easy way for code inside java.base to access the one true builtin FileSystemProvider.
        Here's an experimental change that works for us:

        @@ -34,10 +34,14 @@
         public class DefaultFileSystemProvider {
             private DefaultFileSystemProvider() { }
         
        + private static final LinuxFileSystemProvider theFileSystemProvider
        + = new LinuxFileSystemProvider();
        +
             /**
              * Returns the default FileSystemProvider.
              */
             public static FileSystemProvider create() {
        - return new LinuxFileSystemProvider();
        + return theFileSystemProvider;
             }
         }

        but of course it's incomplete...

        The name "create" strongly suggests a new instance is returned, but those are not the sermantics we want. We could rename it to "get" or "instance".
        Of course we would want to fix all the OSes, not just Linux. Maybe there's a refactoring that works well. Maybe we should migrate those Holder classes from FileSystems.java into a location where it can be used by the rest of java.base.

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  martin Martin Buchholz
                  Reporter:
                  martin Martin Buchholz
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  11 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved: