web-dev-qa-db-ja.com

Runtime.exec()。waitFor()は実際には待機していません

Runtime.exec()を使用して外部.jar(IzPackインストーラーとしてビルド)を実行するコードがいくつかあります。

このexternal.jarをコマンドラインから次のように実行すると、次のようになります。

_Java -jar external.jar
_

次に、コマンドPromptは、アプリケーションが終了するまで制御を返しません。ただし、いくつかのJavaクラス内からexternal.jarを実行すると、次を使用します。

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

次に、external.jarがまだ実行を完了していないにもかかわらず、pは成功コード_0_でほぼ瞬時に戻ります(外部ファイル実行のProcessBuilderルートを介してこれも試しました) )。

別のJavaプログラム内から実行された場合ではなく、コマンドラインから戻るのを待つのはなぜですか?

また、A、B、Cの3つのjarを設定しました。ここで、AはCを呼び出すBを呼び出します(Runtime.exec()を使用)。ここで、C _Thread.sleep_ sは10秒間、簡単なテストとして、予想どおり、Aは実行後10秒まで戻りません。

これはおそらくexternal.jarのスレッドの問題であり、実行が1つのものから別のものに引き継がれていると思いますが、コマンドラインから直接機能することを考えると、同じ動作が見られると予想されます(おそらく素朴に)別のJavaプログラム内から呼び出された場合。

私はこれをWindowsとUbuntuでJava 6でテストしました。

ありがとう!

12
Rhys

これを実現する別の可能な方法は、プロセスの出力をキャプチャして、それが終了するのを待つことです。

例えば:

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()ですが、実行しているプログラムによっては、プロセス出力ストリームは次のようになります。

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

これをwhileループで実行すると、プログラムはプロセスの終了を待機するようになります。

6

ProcessBuilderを使用できます。

ProcessBuilder pb = new ProcessBuilder("Java", "-jar", "/fielname.jar");
Process p = pb.start();
p.waitFor();
1
Vishal Bhosale

プロセスの生成を処理するために新しいスレッドを生成していますか?その場合、元のプログラムは生成されたプロセスとは独立して動作し続けるため、waitFor()は新しいプロセスでのみ機能し、親では機能しません。

0
Matt Westlake