有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java:关闭子进程std流?

^{}的javadoc:

The methods that create processes may not work well for special processes on certain native platforms, such as native windowing processes, daemon processes, Win16/DOS processes on Microsoft Windows, or shell scripts. The created subprocess does not have its own terminal or console. All its standard io (i.e. stdin, stdout, stderr) operations will be redirected to the parent process through three streams (getOutputStream(), getInputStream(), getErrorStream()). The parent process uses these streams to feed input to and get output from the subprocess. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.

我知道这个问题,当然,如果你想与子流程沟通,及时与它沟通是有意义的

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

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

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

我还需要担心僵局吗?(例如,如果子流程持续向自己的标准输出数据)


共 (1) 个答案

  1. # 1 楼答案

    你有两件事需要担心:

    1. 当您无法使用stdout时,进程是否会阻塞并试图写入它,以及
    2. 流程将如何解释关闭的流

    关闭输出流显然不会导致死锁,除非流程需要输入。然而,进程检测到已到达流的末尾,并可能相应地终止。以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);
          }
       }
    }
    

    进程正常结束,父进程终止,显示0退出代码

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

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