16

我正在处理的应用程序突然崩溃了

java.io.IOException: ... Too many open files

据我了解,这意味着文件已打开但未关闭。

Stacktrace 当然是在事后发生的,只能帮助了解发生什么事件错误之前。

什么是搜索代码库以查找此问题的智能方法,该问题似乎仅在应用程序处于高压力负载下时才会发生。

4

4 回答 4

15
  1. 用于 lsof -p pid检查导致文件引用泄漏的原因;

  2. 用于ulimit -n查看单个进程打开文件引用的限制;

  3. 检查你项目中的任何IO资源,是否及时释放? ,注意File,,,,(和Http连接)都是IO资源。ProcessSocket

  4. 有时,太多的线程也会导致这个问题。

于 2013-04-11T15:30:27.047 回答
14

我认为使用专门为此目的设计的工具的最佳方法,例如这个

这个小型 Java 代理是一个工具,可以跟踪在 JVM 中打开文件的位置/时间/人员。您可以让代理跟踪这些操作以了解访问模式或处理泄漏,并转储当前打开的文件列表以及打开它们的位置/时间/谁。

此外,在“打开的文件过多”异常时,此代理将转储列表,让您找出大量文件描述符正在使用的位置。

我似乎记得YourKit在这方面也有一些设施,但目前找不到任何具体信息。

于 2013-04-11T15:24:26.663 回答
3

什么操作系统?如果是 linux/mac,那么/proc 下的信息应该会有所帮助。在 Windows 上,使用Process Explorer

至于搜索代码库,也许寻找捕获或引发的代码IOException- 我认为已经捕获/引发这个的 I/O 方法很可能需要close()调用。

于 2013-04-11T15:23:35.413 回答
3

您是否尝试过使用 jvisualvm(Java 5.0 及更高版本在 JDK bin 目录中)附加到正在运行的进程。您可以打开正在运行的进程并进行堆转储(如果您有较旧的 JDK,则需要使用 eclipse 或 intellij 或 netbeans 等进行分析)。

在 JDK 7 中,堆转储按钮位于“监视器”选项卡下。它将创建一个堆转储选项卡,“类”子选项卡,您可以检查并查看是否存在大量打开文件的任何类。另一个非常有用的功能是堆转储比较,因此您可以获取一个参考堆转储,让您的应用程序运行一下,然后再获取另一个堆转储并比较两者(比较链接在您获得的“[heapdump]”选项卡上当你拿一个时。java中还有一个标志用于在崩溃或OOM异常时进行堆转储,如果比较堆转储没有给你一个导致问题的明显类,你可以沿着这条路线走。另外,“实例”堆转储差异中的子选项卡将向您显示两个堆转储之间的时间分配的内容,这也可能有所帮助。

jvisualvm 是一个很棒的工具,但没有得到足够的提及。

于 2013-04-11T15:48:31.680 回答