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

时间:2010-02-16 12:45:17

标签: java jvm

我在Java中遇到这个异常:

java.io.FileNotFoundException: (Too many open files) 

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

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

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

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

当我接近-Xmx中指定总数的1%时,我正在监视空闲堆大小并引发“警报”。我也知道,如果我的线程数达到500以上,那么肯定会失控。现在,有一种方法可以知道我的JVM从操作系统中分配太多句柄并且不会将它们退回,例如插座,打开的文件等。如果我知道,我知道在哪里看,什么时候。

5 个答案:

答案 0 :(得分:29)

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

lsof -p <pid of jvm>

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

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

答案 1 :(得分:24)

由于您使用的是Linux,我建议您检查/ proc-Filesystem。在proc中,您将找到一个文件夹,其中包含文件夹calld'fd'的进程的PID。如果您的进程ID为1234,则路径为

/proc/1234/fd

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

答案 2 :(得分:12)

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

sudo lsof > lsof.log

显示坏人(来自@ 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

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

sudo ls -l /proc/114970/fd > fd.log

显示热门打开的文件:

cat fd | awk '{ print $11 }' | sort -rn | uniq -c | sort -rn | head -n20

答案 3 :(得分:10)

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

* soft nofile 2048 # Set the limit according to your needs
* hard nofile 2048

然后,您可以在shell上使用sysctl -p重新加载配置。检查this article

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

答案 4 :(得分:1)

如果您使用的是MacOS

sudo launchctl limit maxfiles <hard> <soft>
sudo launchctl limit maxfiles 1024 200000