12

我有一些代码使用 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 个罐子,A、B 和 C,其中 A 调用 B 调用 C(使用Runtime.exec()),其中 CThread.sleep持续 10 秒,作为一个简单的测试,并且正如预期的那样,A 直到 10 秒后才返回它运行。

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

我已经使用 Java 6 在 Windows 和 Ubuntu 上对此进行了测试。

谢谢!

4

5 回答 5

6

another possible way to achieve this might be to capture the output of the process and wait for it to finish.

For example:

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
}

Normally the output stream is tr.getInputStream() but depending on the program you are executing the process output stream migh be:

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

By doing this while loop you force your program to wait the process to finish.

于 2013-12-30T08:32:54.550 回答
1

您可以使用流程生成器....

ProcessBuilder pb = new ProcessBuilder("java", "-jar", "/fielname.jar");
Process p = pb.start();
p.waitFor();
于 2015-10-23T10:52:54.320 回答
0

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

于 2012-07-05T19:06:07.447 回答
-1

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);
 }
于 2012-09-07T06:19:51.743 回答
-2

我在使用控制台执行某些软件的过程中遇到了同样的问题,我只是使用 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.
于 2013-12-10T10:31:33.850 回答