Runtime.exec()。waitFor()实际上并没有等待

我有一些代码使用Runtime.exec()来运行外部.jar(构建为IzPack安装程序)。

如果我从命令行运行这个external.jar,如下所示:

java -jar external.jar 

然后,在应用程序完成之前,命令提示符不会返回控件。 但是,如果我从某个java类中运行external.jar,则使用:

 Process p = Runtime.getRuntime().exec("java -jar external.jar"); int exitCode = p.waitFor(); System.out.println("Process p returned: " + exitCode); 

然后p几乎立即返回,成功代码为0 ,尽管external.jar尚未完成执行(我也通过ProcessBuilder外部文件执行路径尝试了这一点)。

为什么它等待从命令行返回,但是从另一个java程序执行时却没有?

我还设置了3个jar子,A,B和C,其中A调用B调用C(使用Runtime.exec() ),其中C Thread.sleep s为10秒,作为一个简单的测试,并且如预期的那样,A在运行10秒后才返回。

我认为这可能是external.jar的某种线程问题,其中执行是从一件事移交给另一件事,但鉴于它直接从命令行工作,我希望看到相同的行为(也许是天真的)从另一个java程序中调用时。

我已经在Windows和Ubuntu上用Java 6测试了这个。

谢谢!

另一种可能的方法是捕获进程的输出并等待它完成。

例如:

 Process tr = Runtime.getRuntime().exec( new String[]{"wkhtmltopdf",mainPage,mainPagePDF}); BufferedReader stdOut=new BufferedReader(new InputStreamReader(tr.getInputStream())); String s; while((s=stdOut.readLine())!=null){ //nothing or print } 

通常输出流是tr.getInputStream()但是根据您正在执行的程序输出流migh是:

  • tr.getInputStream()
  • tr.getErrorStream()
  • tr.getOutputStream()

通过执行此循环,您可以强制程序等待该过程完成。

您可以使用Process Builder ….

 ProcessBuilder pb = new ProcessBuilder("java", "-jar", "/fielname.jar"); Process p = pb.start(); p.waitFor(); 

您是否正在产生一个新线程来处理该过程的产生? 如果是这样,原始程序将继续独立于生成的进程运行,因此waitFor()将仅适用于新进程而不是父进程。

Process.waitFor()对于某些本机系统命令没用。

您需要获取进程的输出以确定它是否已返回。

我为你写了一个示例代码

 /** * * @param cmdarray command and parameter of System call * @param dir the directory execute system call * @param returnImmediately true indicate return after system call immediately; * false otherwise. * if set true, the returned call result does not have reference value * @return the return code of system call , default is -1 */ public static int systemCall(String[] cmdarray,File dir,boolean returnImmediately) { int result = -1; try { Process p = Runtime.getRuntime().exec(cmdarray,null,dir); if(!returnImmediately) { java.io.InputStream stdin = p.getInputStream(); java.io.InputStreamReader isr = new java.io.InputStreamReader(stdin); java.io.BufferedReader br = new java.io.BufferedReader(isr); String line = null; while ( (line = br.readLine()) != null) System.out.println(line); } try{result = p.exitValue();} catch(Exception ie){;} } catch (IOException e) { e.printStackTrace();} return result; } public static void main(String[] argc){ String[] cmdarray = {"jar","cvf","s2.jar","*"}; File dir = new File("D:\\src\\struts-2.3.1"); int k = systemCall(cmdarray,dir,true); System.out.println("k="+k); } 

我使用进程使用控制台执行某些软件时遇到了同样的问题,我只是使用process.waitFor()解决了它

对我来说它完美无缺。

  try{ Process tr = Runtime.getRuntime().exec( new String[]{ "wkhtmltopdf",frontPage,frontPagePDF}); tr.waitFor(); } catch (Exception ex) { EverLogger.logEntry("Error al pasar a PDF la portada", "error", "activity"); return; } some more code here.