Java在尝试关闭ProcessBuilder输出流时挂起
我有以下Java代码来启动ProcessBuilder,打开OutputStream,让流程将字符串写入OutputStream,然后关闭OutputStream。当我试图关闭OutputStream时,整个事件将无限期地挂起。这只发生在Windows上,而不是Mac或Linux上 一些相关的问题似乎与我遇到的问题很接近,但我还没有弄清楚如何将答案应用到我的问题上,因为我是Java的新手。这是代码。你可以看到,我加入了很多println语句,试图隔离问题Java在尝试关闭ProcessBuilder输出流时挂起,java,process,Java,Process,我有以下Java代码来启动ProcessBuilder,打开OutputStream,让流程将字符串写入OutputStream,然后关闭OutputStream。当我试图关闭OutputStream时,整个事件将无限期地挂起。这只发生在Windows上,而不是Mac或Linux上 一些相关的问题似乎与我遇到的问题很接近,但我还没有弄清楚如何将答案应用到我的问题上,因为我是Java的新手。这是代码。你可以看到,我加入了很多println语句,试图隔离问题 System.out.print
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正在准备将输入文件写入out
GenMic在我身上发生这种情况时已经完成了对out的写入,这是因为我没有读取进程写入的流中的所有内容 java.lang.Process类的API文档说: 创建的子流程没有自己的终端或控制台。其所有标准io(即stdin、stdout、stderr)操作将通过三个流(getOutputStream()、getInputStream()、getErrorStream())重定向到父进程。父进程使用这些流向子进程提供输入并从中获取输出。由于某些本机平台仅为标准输入和输出流提供有限的缓冲区大小,因此未能及时写入子流程的输入流或读取子流程的输出流可能会导致子流程阻塞,甚至死锁
我将尝试在流程实例上调用getInputStream(),并编写一个循环,每次读取一个字节,直到它达到EOF。我会对getErrorStream()执行同样的操作,以防进程正在写入stderr。您是否从进程的stdout/stderr中读取了任何内容
很可能进程试图输出某些内容,但由于无人读取输出而被阻止。这意味着您的
out.flush()
或out.close()
阻塞,因为进程无法处理输入,因为它的输出被阻塞。您需要确保getInputStream()
和getOutputStream()返回的流
在各个线程上被排空,这些线程与关闭getOutputStream()返回的流的线程不同
基本上,如果您想操作和检查其stdin、stdout和stderr,每个子进程至少需要3个线程。根据您的情况,其中一个线程可能是您当前的执行线程(您创建ProcessBuilder的线程)。感谢Nathan的快速响应。在我显示的代码之后几行,我确实使用getInputStream()读取了子流程的输出,但代码在到达之前挂起。“未及时书写”是什么意思?我正在尝试在打开OutputStream后立即写入。我还能做什么?再次感谢。所以你永远不会达到“GenMic closed OutputStream”的程度,对吗?你一定有例外,能给我们看看吗?否则,我会尝试关闭输出流,直到从inputstream读取所有内容,但这只是一个猜测。没错。。。它永远不会到达“GenMic closed OutputStream”。我知道我用OutputStream.write()命令创建的文件已经完全写入,因为即使进程仍然挂起,我也可以打开它并查看它。您可以看到,我已将println放入以获取任何异常消息,但它们都不会被触发。我将尝试您的建议,等待关闭输出流,直到从输入流读取所有内容。“我确实在显示代码后几行使用getInputStream()读取子流程的输出,但代码在到达之前挂起”。。。因此,你应该先这样做。换句话说,在一个单独的线程中。两个线程,一个用于输出,一个用于err。如果在输入时在同一个线程中读取输出,则很容易死锁。想想看,您试图写入进程,但它会阻塞,因为您的线程尚未读取其输出。由于你阻塞了,你的单线程不能前进到它从程序中读取的点。我有一个问题,我认为这是解决方案,但我必须尝试一下。从目前为止我所看到的情况来看,要找到关于如何使用流程和流的信息并不容易。关于并发性的Java教程有一句好话,“多进程应用程序不在本文档的范围之内”。。。