Java ProcessBuilder 启动的进程阻塞不退出问题。

https://wiki.sei.cmu.edu/confluence/display/java/FIO07-J.+Do+not+let+external+processes+block+on+IO+buffers

 

java通过调用进程读取输出启动进程的标准输出时,如果被调用进程的,标准输出以及错误流的缓冲区被写满, 后续写入会导致调用进程会卡住,无法正常结束。 

确保waiffor之前读取清空了所有流数据,并在waitfor 之后 关闭流。 在waifor 之前关闭仍有可能卡住!

 

These processes may require input to be sent to their input stream, and they may also produce output on their output stream, their error stream, or both. Incorrect handling of such external programs can cause unexpected exceptions, denial of service (DoS), and other security problems.

A process that tries to read input on an empty input stream will block until input is supplied. Consequently, input must be supplied when invoking such a process.

Output from an external process can exhaust the available buffer reserved for its output or error stream. When this occurs, the Java program can block the external process as well, preventing any forward progress for both the Java program and the external process. Note that many platforms limit the buffer size available for output streams. Consequently, when invoking an external process, if the process sends any data to its output stream, the output stream must be emptied. Similarly, if the process sends any data to its error stream, the error stream must also be emptied.

 

合格的代码(合并错误流, 并完全读取)

复制代码
public class Exec {
  public static void main(String args[])
                          throws IOException, InterruptedException {
    ProcessBuilder pb = new ProcessBuilder("notemaker");
    pb = pb.redirectErrorStream(true);
    Process proc = pb.start();
    InputStream is = proc.getInputStream();
    int c;
    while ((c = is.read()) != -1) {
      System.out.print((char) c);
    }
    int exitVal = proc.waitFor();
  }
}
复制代码

合格的代码2 

复制代码
class StreamGobbler implements Runnable {
  private final InputStream is;
  private final PrintStream os;
 
  StreamGobbler(InputStream is, PrintStream os) {
    this.is = is;
    this.os = os;
  }
 
  public void run() {
    try {
      int c;
      while ((c = is.read()) != -1)
          os.print((char) c);
    } catch (IOException x) {
      // Handle error
    }
  }
}
 
public class Exec {
  public static void main(String[] args)
    throws IOException, InterruptedException {
 
    Runtime rt = Runtime.getRuntime();
    Process proc = rt.exec("notemaker");
 
    // Any error message?
    Thread errorGobbler
      = new Thread(new StreamGobbler(proc.getErrorStream(), System.err));
  
    // Any output?
    Thread outputGobbler
      = new Thread(new StreamGobbler(proc.getInputStream(), System.out));
 
    errorGobbler.start();
    outputGobbler.start();
 
    // Any error?
    int exitVal = proc.waitFor();
    errorGobbler.join();   // Handle condition where the
    outputGobbler.join();  // process ends before the threads finish
  }
}
复制代码

 

posted @   锅叔  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示