尝试关闭ProcessBuilder OutputStream时,Java挂起

时间:2010-05-06 17:41:16

标签: java process

我有以下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写完了

3 个答案:

答案 0 :(得分:3)

当我遇到这种情况时,那是因为我没有从流程中写入的流中读取所有内容。

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

  

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

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

答案 1 :(得分:3)

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

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

答案 2 :(得分:1)

你有从stdout / stderr读取过程的任何内容吗?

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