FileSystems.getDefault().getPath() vs Paths.get() and resource leakage

2k Views Asked by At

If I use FileSystems.getDefault().getPath() it holds resource at FileSystems.getDefault(). Few tools like sonar, coverity give high impact issues of resource leak for using this.

If I replace it with Paths.get() all the such tools quietly accept this and there is no error or warning of resource leak.

If we see the implementation of Paths.get(), it is literally doing FileSystems.getDefault().getPath()

My question here is, how does java handle resource leak for Paths.get() because the code is exactly same but we don't have reference to FileSystems.getDefault() to explicitly close it?

2

There are 2 best solutions below

3
Rob Spoor On

Your tools are reporting a false positive. That's because the declared type returned by FileSystems.getDefault(), FileSystem, implements Closeable. That means that ideally you should close it. However, the default file system is an exception (it even throws an UnsupportedOperationException). Your tools cannot make that distinction.

This happens more often than you'd think. Some examples I've seen too often:

  • The result of Objects.requireNonNull. The input is returned as-is, but if the input is AutoCloseable my IDE treats it as a new resource.
  • The input stream or reader from a servlet request, and the output stream or writer from a servet response.

There are some cases where tools and IDEs can be smart. For instance, if I declare a variable as ByteArrayInputStream, ByteArrayOutputStream, StringReader or StringWriter, then my IDE knows they don't need to be closed. However, when I return these from a method as InputStream, OutputStream, Reader or Writer respectively, my IDE starts complaining if I don't close them.

If you know that it is a false positive, you can use @SuppressWarnings("resource") to ignore warnings by some tools. That can often be applied to single variables:

@SuppressWarnings("resource") FileSystem defaultFS = FileSystems.getDefault();
Path path = defaultFS.getPath("foo");

However, even then sometimes your tools will complain, and you have to suppress the resource warnings for the entire method. If that's the case, try to keep your method (and therefore the scope of the warning suppression) as small as possible; split off code to a new method if needed.

0
Udara S.S Liyanage On

This is a false positive when running in a Linux environment.

When running in a Linux environment, FileSystems.getDefault() is an exception to this rule. Actually, if you try to close, it will throw an exception. Check the source code

  public final void close() throws IOException {
        throw new UnsupportedOperationException();
    }

https://github.com/openjdk/jdk/blob/master/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java#L155