Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/370.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java:关闭子进程std流?_Java_Subprocess_Blocking - Fatal编程技术网

java:关闭子进程std流?

java:关闭子进程std流?,java,subprocess,blocking,Java,Subprocess,Blocking,从javadoc获取: 在某些本机平台上,创建进程的方法可能无法很好地用于特殊进程,例如本机窗口进程、守护进程、Microsoft Windows上的Win16/DOS进程或shell脚本。创建的子流程没有自己的终端或控制台。其所有标准io(即stdin、stdout、stderr)操作将通过三个流(getOutputStream()、getInputStream()、getErrorStream())重定向到父进程。父进程使用这些流向子进程提供输入并从中获取输出。由于某些本机平台仅为标准输入和

从javadoc获取:

在某些本机平台上,创建进程的方法可能无法很好地用于特殊进程,例如本机窗口进程、守护进程、Microsoft Windows上的Win16/DOS进程或shell脚本。创建的子流程没有自己的终端或控制台。其所有标准io(即stdin、stdout、stderr)操作将通过三个流(getOutputStream()、getInputStream()、getErrorStream())重定向到父进程。父进程使用这些流向子进程提供输入并从中获取输出。由于某些本机平台仅为标准输入和输出流提供有限的缓冲区大小,因此未能及时写入子流程的输入流或读取子流程的输出流可能会导致子流程阻塞,甚至死锁

我知道这个问题,当然,如果您希望与子流程进行通信,那么及时地与子流程进行通信是有意义的

但是如果您只想启动一个进程而不关心I/O呢?在Java中,有没有一种方法可以释放父进程中专用于管理子进程的资源?(例如,I/O管道和等待子流程退出状态)

如果我在父进程中执行以下操作:

  Process.getOutputStream().close();
  Process.getInputStream().close();
  Process.getErrorStream().close();

我还需要担心僵局吗?(例如,如果子进程不断地将数据发送到自己的标准输出)

这里您需要担心两件事:

  • 当您无法使用stdout时,进程是否会阻塞并试图写入它,以及
  • 流程将如何解释关闭的流
  • 关闭输出流显然不会导致死锁,除非进程需要输入。然而,该过程将检测到已经到达流的结尾,并且可以相应地终止。以
    grep
    为例。此程序将在您关闭其输入流时终止


    忽略输入最简单、最安全的方法是创建一个库,在单独的线程上使用和丢弃输入。您可能已经看到了浮动的类
    StreamGobbler
    ,它就是这样做的

    编辑 因此,我尝试了以下两个不同的子流程程序:

    Process proc = new ProcessBuilder(appStr).start();
    proc.getInputStream().close();
    
    InputStream eos = proc.getErrorStream();
    BufferedReader reader = new BufferedReader(new InputStreamReader(eos));
    for ( String line = null; (line = reader.readLine()) != null; ) {
       System.err.println(line);
    }
    
    System.out.println(proc.waitFor());
    
    第一次,我调用了一个简单的Java应用程序:

    public class App {
       public static void main(String[] args) throws Exception {
          for ( int i = 0; i < 1000; i++ ) {
             System.out.println(i);
          }
       }
    }
    
    公共类应用程序{
    公共静态void main(字符串[]args)引发异常{
    对于(int i=0;i<1000;i++){
    系统输出打印LN(i);
    }
    }
    }
    
    进程正常结束,父进程终止,显示退出代码

    但后来我尝试对一个本机程序调用它,在本例中是一个
    cat
    变体,回显一个文件。在这种情况下,子进程失败,并向错误流写入一条乱码消息,抱怨标准输出流已关闭。它以非零退出代码异常终止


    因此,实际上,在一般情况下,您在关闭流方面的建议不会成功。您必须知道,子进程可以优雅地处理丢失的输出流,我怀疑大多数应用程序不会。我的直觉是,当输出流关闭时,Java可以做一些优雅的失败,从程序的角度来看,流仍然是打开的,没有人监听。

    “忽略输入的最简单和最安全的方法是创建一个库,在单独的线程上使用和丢弃输入”——我同意,我只是不想为派生的子流程使用更多的资源,除非我必须这样做。我只想让子流程自己做事情。(在这里插入疏忽的养育类比)@Jason:我做了更多的测试,并在上面包含了我的发现。好的,很酷,非常感谢。在我短期内担心的情况下,这是一个JVM启动了第二个JVM,所以听起来它会工作得很好(或者至少关闭会比根本不处理stdout/stderr流更好)