如何测试“Too Many Files Open”问题

时间:2010-08-27 19:11:12

标签: java tdd spring-batch

我有一个批处理过程,可以将WAV顺序转换为MP3。问题是,在几千个文件后,有太多文件未打开,并且它会在文件限制下运行。

它之所以这样做是因为SystemCommandTasklet中的代码:

FutureTask<Integer> systemCommandTask = new FutureTask<Integer>(new Callable<Integer>() {
    public Integer call() throws Exception {
        Process process = Runtime.getRuntime().exec(command, environmentParams, workingDirectory);
        return process.waitFor();
    }
});

这有一个令人讨厌的副作用,就是让我依赖JVM来清理进程,让文件保持打开等等。

我已将其重写为:

FutureTask<Integer> systemCommandTask = new FutureTask<Integer>(new Callable<Integer>() {
    public Integer call() throws Exception {
        Process process = Runtime.getRuntime().exec(command, environmentParams, workingDirectory);
        int status = process.waitFor();

        process.getErrorStream().close();

        process.getInputStream().close();

        process.getOutputStream().flush();
        process.getOutputStream().close();

        process.destroy();

        return status;
    }

});

我95%确定这可以在我的Mac上运行(感谢lsof),但是我如何进行适当的测试以适用于任何系统以证明我正在尝试做的实际上是在工作?

3 个答案:

答案 0 :(得分:1)

  1. 您不应该使用Runtime#exec(),因为该进程未附加到JVM上。请查看j.l.ProcessBuilder,它返回一个由JVM进程控制的进程。因此,倾销流程可能会迫使系统释放/关闭资源。
  2. 您应该使用j.u.c.Executors安排和限制流程。
  3. 您也可以使用“ulimit -Sn”读取限制(“ulimit -Hn”不应该因系统健康而优先;)。
  4. 检查转换媒体的工具是否在完成后保留资源(泄漏,等待来电者信号等)。

答案 1 :(得分:0)

您可以尝试编码以避免它。

为什么不主动限制100个任务的数量?

在这种情况下,您可以使用一些池化机制来执行像Thread Pools一样的工作。

答案 2 :(得分:0)

证明很难。但是......

创建一个(虚拟)命令,它不会做太多事情,但会保持对文件的锁定,就像真实的一样。这可以确保您的测试不依赖于所使用的实际命令。

使用旧版本创建一个启动SystemCommandTask的测试,但使用DummyCommand。让它经常启动任务,直到你得到预期的异常。让我们调用所需的任务数量

更改测试以启动100xN任务。

将任务更改为新版本。如果测试变为绿色,则应该合理地确保您的代码有效。