首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Files.walkFileTree泄漏带有自定义FileVisitor的目录描述符

Files.walkFileTree泄漏带有自定义FileVisitor的目录描述符
EN

Stack Overflow用户
提问于 2017-10-18 12:00:30
回答 1查看 418关注 0票数 0

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

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

代码语言:javascript
复制
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就像在中一样。

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

代码语言:javascript
复制
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。这不应该是垃圾收集吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-10-18 15:43:11

来自文档

返回的流封装了一个DirectoryStream。如果需要及时处理文件系统资源,则应使用“使用资源进行尝试”结构来确保流操作完成后调用流的关闭方法。

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

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46809700

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档