调试“打开的文件太多”问题

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

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

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

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

什么是一种智能的方式来搜索你的代码库来找到这个问题,这似乎只是在应用程序处于高压力负载时才会发生。

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

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

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

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

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

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

  3. 检查项目中的任何IO资源,它们是否及时发布?注意, FileProcessSocket (和Http连接)都是IO资源。

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

什么OS? 如果它是linux / mac, / proc下的信息应该有帮助。 在Windows上,使用Process Explorer 。

在搜索代码库时,可能会查找捕获或引发IOException代码 – 我认为已经捕获/引发此问题的I / O方法很可能需要close()调用。

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

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

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