尝试关闭ProcessBuilder OutputStream时,Java挂起

我有以下Java代码来启动ProcessBuilder,打开一个OutputStream,让进程将一个字符串写入一个OutputStream,然后关闭OutputStream。 当我尝试关闭OutputStream时,整个事情无限期地挂起。 这只发生在Windows上,从不在Mac或Linux上发生。

一些相关的问题似乎与我遇到的问题很接近,但我无法弄清楚如何应用我的问题的答案,因为我是Java的相对新手。 这是代码。 你可以看到我已经放入了很多println语句来试图找出问题所在。

System.out.println("GenMic trying to get the input file now"); System.out.flush(); OutputStream out = child.getOutputStream(); try { System.out.println("GenMic getting ready to write the input file to out"); System.out.flush(); out.write(intext.getBytes()); // intext is a string previously created System.out.println("GenMic finished writing to out"); System.out.flush(); out.close(); System.out.println("GenMic closed OutputStream"); System.out.flush(); } catch (IOException iox) { System.out.println("GenMic caught IOException 2"); System.out.flush(); String detailedMessage = iox.getMessage(); System.out.println("Exception: " + detailedMessage); System.out.flush(); throw new RuntimeException(iox); } 

以下是执行此块时的输出:

GenMic现在尝试获取输入文件

GenMic准备将输入文件写出来

GenMic完成了写作

当那件事发生在我身上时,那是因为我没有从流程写入的流中读取所有内容。

java.lang.Process类的API文档说:

创建的子进程没有自己的终端或控制台。 它的所有标准io(即stdin,stdout,stderr)操作将通过三个流(getOutputStream(),getInputStream(),getErrorStream())重定向到父进程。 父进程使用这些流向子进程提供输入并从子进程获取输出。 由于某些本机平台仅为标准输入和输出流提供有限的缓冲区大小,因此无法及时写入输入流或读取子进程的输出流可能导致子进程阻塞,甚至死锁。

我会尝试在Process实例上调用getInputStream()并编写一个循环来一次读取一个字节,直到它达到EOF。 我会用getErrorStream()做同样的事情,以防进程写入stderr。

您需要确保getInputStream()getOutputStream()返回的流在各个线程上耗尽,并且这些线程与您关闭getOutputStream()返回的流的线程不同。

基本上,如果要操作并检查其stdinstdoutstderr ,则每个子进程至少需要3个线程。 根据您的具体情况,其中一个线程可能是您当前的执行线程(您在其上创建ProcessBuilder的线程)。

你有什么东西从stdout / stderr读取过程吗?

这个过程很可能会尝试输出一些东西,但是因为没有人正在读取输出而被阻止。 这意味着你的out.flush()out.close()阻塞,因为它阻止了输出,因此进程无法处理输入。