Java8 使用 Files.list (),遇到的坑(未关闭流)

公司业务在与第三方业务进行文件交互时,有读取目录下所有文件的操作,采用的是Files.list()方法读取。
程序跑了几天后,报出 java.nio.file.FileSystemException: /data/xml/product/xml_2438.xml: Too many open files 异常。
经过排查,服务器上句柄数设置为了 60000,与没有上限无异了,确认应当是程序的问题。
经过排查和在测试环境测试,使用 lsof -p 检查打开的文件句柄时可以看到的打开文件句柄列表变得越来越长,原因是使用 Files.list() 方法打开文件后未明确的关闭流,将会消耗大量的系统资源,使用 try-with-resources 关闭流,有相同问题的还有 Files.lines 方法,最终修改代码为:

        // 删除bad文件下的车牌图
        try (Stream<Path> list = Files.list(Paths.get(badFilesPath))) {
            List<Path> badFiles = list.filter(path -> !Files.isDirectory(path) && path.getFileName().toString().endsWith(".jpg"))
                    .collect(Collectors.toList());
            if (!badFiles.isEmpty()) {
                for (Path badFile : badFiles) {
                    Files.delete(badFile);
                }
            }
            badFiles.clear();
        }

如果关闭Stream,Files.list()确实会关闭其用于流式传输文件的底层DirectoryStream,因此只要关闭Stream,就不会有资源泄漏。
要了解的关键是,使用关闭流本身时会调用的Runnable向流中注册Stream::onClose。该Runnable是通过工厂方法asUncheckedRunnable创建的,该方法创建一个Runnable来关闭传递给它的资源,并将在IOException期间引发的所有close()转换为UncheckedIOException

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cyufeng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值