FULL PRODUCT VERSION :
openjdk 17.0.11 2024-04-16
OpenJDK Runtime Environment Temurin-17.0.11+9 (build 17.0.11+9)
OpenJDK 64-Bit Server VM Temurin-17.0.11+9 (build 17.0.11+9, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
The following test-case with the attached zip-file available on the classpath will show a file-handle leak in FileTreeWalker, i.e. it will not close a DirectoryStream that is opened as part of walking the file-tree.
When looking at source-code of FileTreeWalker, it seems that the stack.pop() in FileTreeWalker.next() should actually call the local method "pop()" which properly closes elements taken from the stack, see https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/nio/file/FileTreeWalker.java#L351 and https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/nio/file/FileTreeWalker.java#L370
Reproducing test-code:
{noformat}
@Test
public void testZipFile() {
URL url = getClass().getResource("/test.zip");
URI uri = URI.create("jar:" + url.getProtocol() + "://" + url.getFile());
try (FileSystem fs = FileSystems.newFileSystem(uri, Collections.emptyMap())) {
assertNotNull(fs);
Files.walkFileTree(fs.getPath("."), new NoopPathVisitor());
} catch (Exception e) {
throw new IllegalStateException("Failed for URI: " + uri, e);
}
}
{noformat}
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
There is no easy way to add an assertion here, but if you debug this you will see that stack.pop() is called without calling "close()" on the underlying DirectoryStream.
REPRODUCIBILITY :
This bug can be reproduced always.
The tool https://github.com/jenkinsci/lib-file-leak-detector also detects and reports this leak:
{noformat}
#4 . by thread:main on Sat Jan 18 17:11:56 CET 2025
at java.base/java.nio.file.Files.newDirectoryStream(Files.java:482)
at java.base/java.nio.file.FileTreeWalker.visit(FileTreeWalker.java:301)
at java.base/java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:323)
at java.base/java.nio.file.Files.walkFileTree(Files.java:2804)
at java.base/java.nio.file.Files.walkFileTree(Files.java:2882)
at org.kohsuke.file_leak_detector.instrumented.FileDemo.testZipFile(FileDemo.java:378)
{noformat}
This is likely not causing much actual issue, but would be good to avoid the false-positives in file-leak-detector.
openjdk 17.0.11 2024-04-16
OpenJDK Runtime Environment Temurin-17.0.11+9 (build 17.0.11+9)
OpenJDK 64-Bit Server VM Temurin-17.0.11+9 (build 17.0.11+9, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
The following test-case with the attached zip-file available on the classpath will show a file-handle leak in FileTreeWalker, i.e. it will not close a DirectoryStream that is opened as part of walking the file-tree.
When looking at source-code of FileTreeWalker, it seems that the stack.pop() in FileTreeWalker.next() should actually call the local method "pop()" which properly closes elements taken from the stack, see https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/nio/file/FileTreeWalker.java#L351 and https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/nio/file/FileTreeWalker.java#L370
Reproducing test-code:
{noformat}
@Test
public void testZipFile() {
URL url = getClass().getResource("/test.zip");
URI uri = URI.create("jar:" + url.getProtocol() + "://" + url.getFile());
try (FileSystem fs = FileSystems.newFileSystem(uri, Collections.emptyMap())) {
assertNotNull(fs);
Files.walkFileTree(fs.getPath("."), new NoopPathVisitor());
} catch (Exception e) {
throw new IllegalStateException("Failed for URI: " + uri, e);
}
}
{noformat}
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
There is no easy way to add an assertion here, but if you debug this you will see that stack.pop() is called without calling "close()" on the underlying DirectoryStream.
REPRODUCIBILITY :
This bug can be reproduced always.
The tool https://github.com/jenkinsci/lib-file-leak-detector also detects and reports this leak:
{noformat}
#4 . by thread:main on Sat Jan 18 17:11:56 CET 2025
at java.base/java.nio.file.Files.newDirectoryStream(Files.java:482)
at java.base/java.nio.file.FileTreeWalker.visit(FileTreeWalker.java:301)
at java.base/java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:323)
at java.base/java.nio.file.Files.walkFileTree(Files.java:2804)
at java.base/java.nio.file.Files.walkFileTree(Files.java:2882)
at org.kohsuke.file_leak_detector.instrumented.FileDemo.testZipFile(FileDemo.java:378)
{noformat}
This is likely not causing much actual issue, but would be good to avoid the false-positives in file-leak-detector.