我们的 Java 应用程序在长时间运行后抛出“打开的文件过多”问题。 调试问题后,可以看到根据 lsof 输出打开了很多 fds。
# lsof -p pid | grep "pipe" | wc -l
698962
# lsof -p pid | grep "anon_inode" | wc -l
349481
------------少量lsof数据------------
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 23994 app 464u 0000 0,9 0 3042 anon_inode
java 23994 app 465u 0000 0,9 0 3042 anon_inode
java 23994 app 466r FIFO 0,8 0t0 962495977 pipe
java 23994 app 467w FIFO 0,8 0t0 962495977 pipe
java 23994 app 468r FIFO 0,8 0t0 963589016 pipe
java 23994 app 469w FIFO 0,8 0t0 963589016 pipe
java 23994 app 470u 0000 0,9 0 3042 anon_inode
java 23994 app 471u 0000 0,9 0 3042 anon_inode
如何找出许多打开 FIFO 和 0000 类型 FD 的根本原因。
在我们的应用程序中发生的文件读/写并不多。使用内部使用 Nio 的 apache mina 框架从流中读取了如此多的 TCP 消息。
这些是我的问题
- 我们检查了/proc/pid/task/文件夹。有很多文件夹。它是否对应于线程 ID?但是根据 jstack,有 141 个线程,而这个文件夹有 209 个子文件夹。
- 如何找到导致 fd 泄漏的线程?在我们的例子中,任务文件夹中的大部分文件夹对应于许多 fds。 IE。/proc/pid/task/threadid/fd文件夹有很多fd记录
- lsof中pipe和anon_inodes可能是什么原因
- FD类型0000是什么意思
- 所有 anon_inode 都具有相同的节点 ID 3042。这是什么意思?
最佳答案
最有可能的情况是您正在打开资源,然后没有正确关闭它们。确保使用适当的方法(例如 try-with-resources 或 try-finally block )进行整理。
要找到问题,您应该通过一个类路由所有 IO,然后跟踪打开和关闭,甚至可能记住堆栈跟踪。然后您可以查询它并查看泄漏资源的位置。
关于java - 查找哪个线程导致打开文件过多问题以及为什么在 lsof 输出中出现重复的节点 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45038400/