Java运行时进程waitfor似乎没有等待

时间:2012-02-21 16:43:41

标签: java process runtime

我必须编写一个程序,通过命令行调用运行其他几个程序。程序1生成一个程序2然后读取的文件。我已经按照各种例子说明了如何安全地做到这一点,但仍然有一个恼人的问题。以下代码在很大程度上有效,但仅限于system.out之后的waitfor()。如果我把它拿出来我会得到错误(见下文)。如果我不知道为什么会发生什么事,我对代码有点不舒服。

任何帮助表示感谢。

代码:

public static int executeCommandWithOutputfile(String command,
      String outputFile) {
   int exitVal = 0;

   try {
      FileOutputStream fos = new FileOutputStream(outputFile);
      Runtime rt = Runtime.getRuntime();
      Process proc = rt.exec(command);

      // any error message?
      StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(),
            "ERROR");

      // any output?
      StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(),
            "OUTPUT", fos);

      // kick them off
      errorGobbler.start();
      outputGobbler.start();

      // any error???
      exitVal = proc.waitFor();
      //don't remove this system out, when I did I got errors.
      //System.out.println("ExitValue: " + exitVal);
      fos.flush();
      fos.close();
   } catch (Throwable t) {
      t.printStackTrace();
   }
   return exitVal;
}

System.out行的输出完好无损:

    ExitValue: 0
    ExitValue: 0
    ExitValue: 0
    Release note complete.

删除了system.out的输出:

    [Fatal Error] tmpRelNote2482381115742032425xml:1:1: Premature end of file.
    Error : The XML config file is not valid!
    Exception in thread "main" java.lang.NullPointerException
        at rwe.release.CreateReleaseNote.insertReleaseInfo(CreateReleaseNote.java:96)
        at rwe.release.CreateReleaseNote.writeReleaseNote(CreateReleaseNote.java:81)
        at rwe.release.CreateReleaseNote.<init>(CreateReleaseNote.java:30)
        at rwe.release.CreateReleaseNote.main(CreateReleaseNote.java:19)
    Process exited with exit code 1.

2 个答案:

答案 0 :(得分:2)

您的代码有竞争条件。当您致电OutputGobbler时,fos.close()可能会或可能不会完成吞噬流程的输出。 println将此线程放慢到足以让gobbler有时间完成处理输出的输出。

在关闭文件之前,必须确保OutputGobbler已完成将所有输出传输到文件。

答案 1 :(得分:0)

你确定问题出在waitFor()吗?

我认为问题在于刷新外部命令的OutputStream,这解释了为什么System.out.println()修复了这个问题。尝试在waitFor()返回后执行显式的System.out.flush()。

来自Process javadoc:“创建的子进程没有自己的终端或控制台。所有标准的io(即stdin,stdout,stderr)操作都将通过三个流重定向到父进程(getOutputStream(),getInputStream( ),getErrorStream())。“