Linux - "太多打开的文件"用管道,如何调试

时间:2014-04-29 21:54:15

标签: java linux ubuntu pipe

我有一个Java程序会抛出太多打开的文件'运行约3分钟后出错。增加打开文件限制不起作用,因为它仍然用尽所有限制,只是更慢。所以我的程序出了问题,我需要找出来。

这是我做的,10970是pid

  • 使用cat /proc/10970/fd检查已打开的Java进程文件,并找出大部分是管道
  • 使用lsof -p 10970 | grep FIFO列出所有管道并查找大约450个管道
  • 管道如下所示
  

java 10970服务1w FIFO 0,8 0t0 5890管道

     

java 10970服务2w FIFO 0,8 0t0 5890管道

     

java 10970 service 169r FIFO 0,8 0t0 2450696 pipe

     

java 10970服务201r FIFO 0,8 0t0 2450708管道

但我不知道如何继续。上面输出中的0,8表示设备编号。如何找到带有这些数字的设备?

更新

该程序是TCP服务器,从客户端和处理消息接收套接字连接。我有两个环境。在生产环境中它工作正常,但在测试环境中它最近有这个问题。在生产环境中,我看不到这么多管道。这两个环境的代码和基础结构是相同的,都由Chef管理。

1 个答案:

答案 0 :(得分:1)

  

但我不知道如何继续。

您需要做的是确定Java代码中打开这些管道的位置......并确保在完成这些管道时它们始终处于关闭状态。

确保管道关闭的最佳方法是在完成管道后明确关闭它们。例如(使用输入流而不是套接字......):

    InputStream is = new FileInputStream("somefile.txt");
    try {
         // Use file
    } finally {
         is.close();
    }

在Java 7或更高版本中,您可以更简洁地将其写为///

    try (InputStream is = new FileInputStream("somefile.txt")) {
         // Use file
    }

在后者中,当InputStream object在隐式try块中完成时,finally会自动关闭。


  上面输出中的

0,8表示设备编号。如何找到带有这些数字的设备?

这可能与解决问题无关。关注文件描述符未被关闭的原因。知道什么设备数字意味着没有帮助。

  

在生产环境中,我看不到这么多管道。

那也许是红鲱鱼。它可能是由GC运行更频繁,并在成为问题之前关闭孤立的文件描述符引起的。

(但强制GC运行不是解决方案。您不应该依赖GC来关闭文件描述符。它效率低且不可靠。)