【问题标题】:Debugging the "Too many files open" issue调试“打开的文件太多”问题
【发布时间】:2013-04-11 15:20:06
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 您是多线程处理文件,还是全部在同一个线程上完成?您是否考虑过并发限制来管理工作负载?
  • @christopher 我正在多线程处理文件。只有当我使用多个线程时才会出现问题。我有一个作业列表,并且只增加线程数以匹配设备上的内核数(例如 4 个),因此在任何给定时间只有 4 个线程处理作业队列。而且工作很快。有任何想法吗?什么是并发限制

标签: java ioexception


【解决方案1】:
  1. 使用lsof -p pid检查导致文件引用泄漏的原因;

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

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

  4. 有时线程过多也会导致此问题。

【讨论】:

  • 根据lsof -p pid,我目前打开了3000个文件,而ulimit -n是2560。可能第一个命令计数不同于文件引用
  • +1 这帮助我调试了一个进程使用不当的安卓应用程序。 Runtime.exec() 与系统的 ping。我不得不在 waitFor() 之后调用 process.destroy() 来修复它。
【解决方案2】:

我认为最好的方法是使用专门为此目的设计的工具,例如this one

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

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

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

【讨论】:

  • 知道如何在 Android 应用程序上使用这个工具吗?
【解决方案3】:

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

就搜索代码库而言,也许寻找捕获或引发 IOException 的代码 - 我认为已经捕获/引发此问题的 I/O 方法很可能需要 close() 调用。

【讨论】:

    【解决方案4】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-05
      • 1970-01-01
      • 2014-06-16
      相关资源
      最近更新 更多