Resource leak in Files.list(Path dir) when stream is not explicitly closed?
If you close the Stream, Files.list()
does close the underlying DirectoryStream
it uses to stream the files, so there should be no resource leak as long as you close the Stream.
You can see where the DirectoryStream
is closed in the source code for Files.list()
here:
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.DISTINCT), false)
.onClose(asUncheckedRunnable(ds));
The key thing to understand is that a Runnable
is registered with the Stream using Stream::onClose
that is called when the stream itself is closed. That Runnable is created by a factory method, asUncheckedRunnable
that creates a Runnable
that closes the resource passed into it, translating any IOException
thrown during the close()
to an UncheckedIOException
You can safely assure that the DirectoryStream
is closed by ensuring the Stream
is closed like this:
try (Stream<Path> files = Files.list(Paths.get(destination))){
files.forEach(path -> {
// Do stuff
});
}
Regarding the IDE part: Eclipse performs resource leak analysis based on local variables (and explicit resource allocation expressions), so you only have to extract the stream to a local variable:
Stream<Path> files =Files.list(Paths.get(destination));
files.forEach(path -> {
// To stuff
});
Then Eclipse will tell you
Resource leak: 'files' is never closed
Behind the scenes the analysis works with a cascade of exceptions:
- All
Closeable
s need closing java.util.stream.Stream
(which is Closeable) does not need closing- All streams produced by methods in
java.nio.file.Files
do need closing
This strategy was developed in coordination with the library team when they discussed whether or not Stream
should be AutoCloseable
.