打开的文件太多:打开的文件数量,打开的数量以及JVM打开的数量

Dim*_*ima 62 java jvm

我在Java中遇到这个异常:

java.io.FileNotFoundException: (Too many open files) 
Run Code Online (Sandbox Code Playgroud)

我正在寻找消除这个问题的方法.

此错误显然表明JVM已分配了太多句柄,而底层操作系统不会让它拥有更多.要么是因为连接不正确/流连接而导致泄漏.

此过程不间断运行数天,最终抛出异常.在12-14天的正常运行时间后反复发生.

你怎么打这个?有没有办法在JVM中获取已分配句柄的列表或在达到一定数量时跟踪?我喜欢打印它们,看看它是如何生长的.我不能使用分析器,因为它是一个生产系统,并且难以在开发中重现它.有什么建议吗?

我正在监视空闲堆大小并在接近-Xmx中指定总数的1%时引发"警报".我也知道,如果我的线程数达到500以上,那么肯定会失控.现在,有没有办法知道我的JVM 从操作系统分配了太多的句柄,并没有给它们回复,例如套接字,打开的文件等.如果我知道这一点,我会知道在哪里看,什么时候.

bra*_*amp 29

您没有说明您正在运行哪个操作系统,但如果您在Linux上运行,则可以使用lsof命令

lsof -p <pid of jvm>
Run Code Online (Sandbox Code Playgroud)

这将列出JVM打开的所有文件.或者,如果您在Windows上运行,您可以使用Process Explorer,它将显示所有进程的所有打开文件.

这样做有望让您缩小代码的哪一部分保持文件打开.

  • 我有兴趣知道我的解决方案是否帮助您追踪问题.如果它不是机密或太麻烦你能解释最终导致问题的原因吗? (2认同)

phi*_*sch 24

既然你在Linux上,我建议你检查/ proc-Filesystem.在proc中,您将找到一个文件夹,其中包含文件夹calld'fd'的进程的PID.如果您的进程ID为1234,则路径为

/proc/1234/fd
Run Code Online (Sandbox Code Playgroud)

在该文件夹中,您将找到所有已打开文件的链接(执行'ls -l').通常,您可以通过文件名告诉哪些库/代码可能打开而不关闭文件.


Jim*_*ian 13

所以,完整的答案(我结合@phisch和@bramp的答案).如果要检查所有进程,则应使用sudo.将结果保存到文件也很好 - lsof并不便宜+此文件可用于进一步调查.

sudo lsof > lsof.log
Run Code Online (Sandbox Code Playgroud)

显示坏人(来自@ Arun评论的UPDATE):

cat lsof.log | awk '{print $1 " " $2 " " $5}' | sort | uniq |awk '{ print $2 " " $1; }' | sort -rn | uniq -c | sort -rn | head -5

    2687 114970 java
    131 127992 nginx
    109 128005 nginx
    105 127994 nginx
    103 128019 nginx
Run Code Online (Sandbox Code Playgroud)

将文件描述符列表保存到文件中:

sudo ls -l /proc/114970/fd > fd.log
Run Code Online (Sandbox Code Playgroud)

显示热门打开文件:

cat fd | awk '{ print $11 }' | sort -rn | uniq -c | sort -rn | head -n20
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢,真的很有用!我想你忘记了第三个命令中的一个部分:它应该是`sudo ls -l/proc/114970/fd> fd.log` (2认同)

gab*_*cio 10

您可以通过添加以下内容来更改已打开文件的限制/etc/security/limits.conf:

* soft nofile 2048 # Set the limit according to your needs
* hard nofile 2048
Run Code Online (Sandbox Code Playgroud)

然后,您可以sysctl -p在shell上重新加载配置.看看这篇文章.

为了完整起见,您可以使用以下方法验证打开文件的当前限制: ulimit -n