因文件流没有关闭而引发的报警

本文详细记录了一次由于文件句柄数超出限制导致的Java服务异常。通过`lsof`和`ulimit`命令确认问题,并发现多个已删除文件仍被占用。初步怀疑是Process类、Guava读文件操作以及文件行数统计代码导致,但尝试修复后问题未解决。最终定位到LOGGER中统计文件行数的代码,使用Java 8的Stream未正确关闭,改为使用try-with-resources语句解决问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

某天一个运行很久没有出问题的服务报警了,查看日志是如下错误,

赶紧排查,搜索“java.io.IOException: error=24, Too many open files”,找到类似的这篇文章(https://blog.youkuaiyun.com/imliuqun123/article/details/103925527),

通过“lsof -p Pid | wc -l” 查看了进程打开的文件总数,使用“ulimit -a”命令查看了系统的限制是多少。发现确实是超了。

通过“lsof -p Pid”命令查看了进程打开的文件的具体名称,发现很多文件后后面都标注了“(deleted)”,

根据文件名称大概定位了是哪部分代码,但具体是哪里出问题了还不确定,毕竟上线运行一段时间了。想着重启一下服务,新的进程就可以将没有用的文件关闭了,于是先重启了一下服务,问题解决,还是要排查出来到底是哪里出问题了呢??

以下是排查思路:

1、 怀疑是Java在Linux下执行命令的时候需要用到Process类,这个类在使用后需要destroy()掉,否者也会导致文件数开启的过多。

使用process.destroy()后问题并没有解决。

2、怀疑是 guava 读取文件  Files.asCharSource(file, Charset.defaultCharset()).readLines(new LineProcessor<String>() {}) 的问题,是这样用的(https://blog.youkuaiyun.com/bobozhangyx/article/details/80529079

但是看源码里是有close的逻辑的,同时使用https://www.baeldung.com/java-read-lines-large-file这里面的FileUtils.lineIterator测试了一下,发现问题还是没有解决。

3、根据打开文件的作用排查看哪里用到了这些文件,发现LOGGER.info(Files.lines(Paths.get(new File(file).getPath())).count());这里有一个统计文件行数的逻辑。

这个逻辑最开始用wc -l实现的,后来改成了files的写法,结果留了一个坑。如果还是用这个方法,需要手动关闭一下stream。具体的看这里 https://qsli.github.io/2017/11/04/java8-file-stream/

try-with-resources语句:https://www.cnblogs.com/aspirant/p/8621848.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值