gpt4 book ai didi

java - Files.walkFileTree 使用自定义 FileVisitor 泄漏目录描述符

转载 作者:行者123 更新时间:2023-12-01 16:47:43 31 4
gpt4 key购买 nike

我在我的应用程序中遇到了一个奇怪的错误。我已经通过解决方法解决了这个问题,但我仍然很好奇为什么会发生这个错误。

下面给出了一个自定义 FileVisitor 的示例,该示例正在删除它所遍历的空目录。如果目录不为空,并且它仍然遍历这些目录,则会泄漏目录描述符。如果我将 lsof 与应用程序的 PID 一起使用,它将显示一堆指向相同的几个目录的描述符,即它遍历的目录。

private String getOldestFile() {
fileVisitor.clearOldestFile();

try {
// FIXME: this was throwing FileSystemException: Too many open files after some time running. Leaking file descriptors!!
Files.walkFileTree(Paths.get(csvPath), fileVisitor);
} catch (IOException e) {
e.printStackTrace();
}

return fileVisitor.getOldestFile().toString();
}

class CustomFileVisitor extends SimpleFileVisitor<Path> {
private Path oldestFile = null;

Path getOldestFile() {
return oldestFile;
}

void clearOldestFile() {
oldestFile = null;
}

@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (attrs.isDirectory())
return FileVisitResult.CONTINUE;

if (oldestFile == null)
oldestFile = file;

if (oldestFile.compareTo(file) > 0)
oldestFile = file;

return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
if (dir.equals(Paths.get(csvPath)))
return FileVisitResult.CONTINUE;

if (Files.list(dir).collect(Collectors.toList()).size() == 0)
Files.delete(dir); // throws an exception if folder is not empty -> mustn't delete folder with files

return FileVisitResult.CONTINUE;
}
}

CustomFileVisitor 仅在外部类中创建一次,并且定期调用该函数,如 filename = getOldestFile();

编辑:发布lsof -p {PID}输出。一开始,我找到PID如this .

这就是 lsof -p {PID} 输出的样子,只是有数千行。 “/home/leon/Development/data/”是 Files.walkFileTree 的输入。

java    14965 leon  285r      DIR                8,2     4096  1970798 /home/leon/Development/data/2017
java 14965 leon 286r DIR 8,2 4096 1970799 /home/leon/Development/data/2017/10
java 14965 leon 287r DIR 8,2 4096 1970799 /home/leon/Development/data/2017/10
java 14965 leon 288r DIR 8,2 36864 1970800 /home/leon/Development/data/2017/10/17
java 14965 leon 289r DIR 8,2 36864 1970800 /home/leon/Development/data/2017/10/17
java 14965 leon 290r DIR 8,2 4096 1970798 /home/leon/Development/data/2017
java 14965 leon 291r DIR 8,2 4096 1970798 /home/leon/Development/data/2017
java 14965 leon 292r DIR 8,2 4096 1970799 /home/leon/Development/data/2017/10
java 14965 leon 293r DIR 8,2 4096 1970799 /home/leon/Development/data/2017/10
java 14965 leon 294r DIR 8,2 36864 1970800 /home/leon/Development/data/2017/10/17
java 14965 leon 295r DIR 8,2 36864 1970800 /home/leon/Development/data/2017/10/17

编辑2:我已设法将问题隔离到这一行:Files.list(dir).collect(Collectors.toList()).size() == 0。这不应该被垃圾收集吗?

最佳答案

来自Files#list() documentation :

The returned stream encapsulates a DirectoryStream. If timely disposal of file system resources is required, the try-with-resources construct should be used to ensure that the stream's close method is invoked after the stream operations are completed.

最终,该流将被垃圾收集,但不会立即进行。所以在这种情况下你必须自己管理。

关于java - Files.walkFileTree 使用自定义 FileVisitor 泄漏目录描述符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46809700/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com