IOException:打开的文件太多

我正在尝试调试在Linux上的Jetty 7.0.1中运行的Java web应用程序中的文件描述符泄漏。

该应用程序已经愉快地运行了一个月左右,当时由于打开的文件太多,请求开始失败,Jetty不得不重新启动。

java.io.IOException: Cannot run program [external program]: java.io.IOException: error=24, Too many open files
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:459)
    at java.lang.Runtime.exec(Runtime.java:593)
    at org.apache.commons.exec.launcher.Java13CommandLauncher.exec(Java13CommandLauncher.java:58)
    at org.apache.commons.exec.DefaultExecutor.launch(DefaultExecutor.java:246)

起初,我认为问题出在启动外部程序的代码上,但它使用的是commons-exec,我没有看到它有什么问题:

CommandLine command = new CommandLine("/path/to/command")
    .addArgument("...");
ByteArrayOutputStream errorBuffer = new ByteArrayOutputStream();
Executor executor = new DefaultExecutor();
executor.setWatchdog(new ExecuteWatchdog(PROCESS_TIMEOUT));
executor.setStreamHandler(new PumpStreamHandler(null, errorBuffer));
try {
    executor.execute(command);
} catch (ExecuteException executeException) {
    if (executeException.getExitValue() == EXIT_CODE_TIMEOUT) {
        throw new MyCommandException("timeout");
    } else {
        throw new MyCommandException(errorBuffer.toString("UTF-8"));
    }
}

列出服务器上打开的文件,我可以看到大量的FIFO:

# lsof -u jetty
...
java    524 jetty  218w  FIFO        0,6      0t0 19404236 pipe
java    524 jetty  219r  FIFO        0,6      0t0 19404008 pipe
java    524 jetty  220r  FIFO        0,6      0t0 19404237 pipe
java    524 jetty  222r  FIFO        0,6      0t0 19404238 pipe

当码头开始时,只有10个FIFO,几天后就有数百个。

我知道这个阶段有点模糊,但是你对下一步在哪里看,或者如何获取有关这些文件描述符的更详细信息有什么建议吗?


答案 1

问题出在您的 Java 应用程序(或您正在使用的库)上。

首先,您应该阅读整个输出(Google for StreamGobbler),然后发音!

Javadoc 说:

父进程使用这些流将输入馈送到子进程并从子进程获取输出。由于某些本机平台仅为标准输入和输出流提供有限的缓冲区大小,因此未能及时写入输入流或读取子进程的输出流可能会导致子进程阻塞,甚至死锁。

其次waitFor() 您的进程终止。然后,应关闭输入、输出和错误流。

最后销毁()你的进程。

我的消息来源:


答案 2

由于您在Linux上运行,我怀疑您正在耗尽文件描述符。看看乌利米特。这是一篇描述该问题的文章:http://www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files/


推荐