从Java开始的子进程使用waitFor完成,但流不会终止

Dav*_*son 6 java processbuilder

我正在使用Java的ProcessBuilder来启动子进程,这是另一个必须在单独的JVM中运行的Java程序.

我启动两个Threads来从Process读取stdout和stderr流,这样如果流缓冲区已满,就没有挂起.对Process.waitFor的调用返回但流不会终止.

我使用的代码看起来像(命令是字符串列表):

ProcessBuilder pb = new ProcessBuilder(command);

final Process p = pb.start();
final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
final ByteArrayOutputStream errStream = new ByteArrayOutputStream();

Thread outputThread = new Thread() {
    @Override
    public void run() {
        try {
            IOUtils.copy(p.getInputStream(), outStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    };
};
outputThread.start();

Thread errorThread = new Thread() {
    @Override
    public void run() {
        try {
            IOUtils.copy(p.getErrorStream(), errStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    };
};
errorThread.start();

int returncode = p.waitFor();
outputThread.join();
errorThread.join();
Run Code Online (Sandbox Code Playgroud)

如果我运行其他东西,例如"java -version"或"dir"或其他东西,代码工作正常.我可以访问我试图运行的Java代码,但我从未听说过你应该在System.out上调用close().

Fab*_*ney 0

据我从这个网站知道,您必须自行关闭 Process 对象中的所有标准流。不管以前用过还是没用过。这似乎与 G1 垃圾收集器(自 Java 7 以来默认)高度相关,G1 垃圾收集器在未显式关闭时保持管道打开 - 即使子进程终止时也是如此。

我不熟悉这里的内部结构,但我在回答问题时发布的代码在经常调用 GhostScript 和其他系统的 24/7 系统上运行良好。

关于 SO 的其他问题和答案指出您必须显式关闭进程的 std-streams: