打开的文件太多:有多少是打开的,它们是什么,以及JVM可以打开多少

2022-08-31 14:48:27

我在Java中得到了这个例外:

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

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

此错误显然表明 JVM 分配了太多的句柄,底层操作系统不会让它拥有更多句柄。要么我在某个地方泄漏了不正确关闭的连接/流。

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

你如何解决这个问题?有没有办法在JVM中获取已分配句柄的列表,或者在达到一定数量时进行跟踪?我很想把它们打印出来,看看它是如何增长的,什么时候长大的。我不能使用分析器,因为它是一个生产系统,在开发过程中很难重现它。有什么建议吗?

我正在监视可用堆大小,并在接近 -Xmx 中指定总数的 1% 时发出“警报”。我也知道,如果我的线程数超过500,那么肯定会有些事情失控。现在,有没有办法知道我的JVM从操作系统分配了太多的句柄并且没有归还它们,例如套接字,打开的文件等。如果我知道这一点,我就会知道在哪里看,什么时候看。


答案 1

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

lsof -p <pid of jvm>

这将列出 JVM 打开的所有文件。或者,如果您在Windows上运行,则可以使用进程资源管理器,它将显示所有进程的所有打开的文件。

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


答案 2

由于您使用的是Linux,我建议您检查/proc-Filesystem。在proc内部,您会发现一个带有进程PID的文件夹,其中包含一个名为“fd”的文件夹。如果进程 ID 为 1234,则路径为

/proc/1234/fd

在该文件夹中,您将找到指向所有打开的文件的链接(执行“ls -l”)。通常,您可以通过文件名判断哪个库/代码可能打开而不是关闭文件。


推荐