9

私はこの SSCCE を試してきましたProcessProcessBuilder

        import java.io.IOException;
        public class TestProcess {
            public static void main(String[] args) {
                Process process = null;
                ProcessBuilder pb = new ProcessBuilder("notepad.exe");

                try {
                    process = pb.start();
                } catch (IOException e) {e.printStackTrace();}

                //have some time to close notepad
                try {
                    Thread.sleep(10*1000);
                } catch (InterruptedException ignored) {}

                try {
                    System.out.println(process.exitValue());
                 } catch (IllegalThreadStateException e) {
                    System.out.println(e);
                 }

                 if (process != null)
                     process.destroy();

                 /*try {
                     Thread.sleep(0, 1);
                 } catch (InterruptedException ignored) {}*/

                 System.out.println(process.exitValue());
             }
         }
  1. このコードを実行して、10 秒のタイムアウト前にメモ帳を閉じると、destroy()呼び出しは、既に終了したプロセスを停止しようとしても問題を示しません。なんで?
  2. このコードを実行し、メモ帳をまったく閉じない場合 (コメント付きの 2 回目のスリープ)

destroy は非同期呼び出し (シグナルを送信するだけですか? ) のようで、2 番目に例外が発生します。exitValue()

 java.lang.IllegalThreadStateException: process has not exited
 Exception in thread "main" java.lang.IllegalThreadStateException: process has not exited
        at java.lang.ProcessImpl.exitValue(ProcessImpl.java:246)
        at TestProcess.main(TestProcess.java:30)
  1. このコードを実行し、メモ帳をまったく閉じない場合 (コメントなしの 2 回目のスリープ) exitValue、スリープ値が 1ms であっても、2 回目は決して例外をスローしません。オーバーヘッド自体が原因ですか?sleep() 2 番目exitValueは 1 を返します。

PS。Windows 7 と Eclipse から実行します。

4

3 に答える 3

1

destroy() メソッドがネイティブ Windows 関数 TerminateProcess を呼び出していることを期待しています。MSDNを見ると、次のことがわかりました。

TerminateProcess は非同期です。終了を開始し、すぐに戻ります。プロセスが終了したことを確認する必要がある場合は、プロセスへのハンドルを指定して WaitForSingleObject 関数を呼び出します。

したがって、destroy が実際に非同期であることを説明していると思います。

同じソースからの別の抜粋:

TerminateProcess 関数は、プロセスを無条件に終了させるために使用されます。

「無条件に」終了プロセスでの destroy() の呼び出しが失敗しない理由を説明できると思います。

この助けを願っています。(本当に興味深い質問です!)

于 2012-12-20T13:17:13.360 に答える
1
  1. なぜ問題が表示されるのでしょうか。すでに破棄されたプロセスを破棄しようとしています。の仕様はProcess.destroy()、破壊するものが何もない場合に何が起こるかを述べていないため、破壊するものが何もない場合、文句を言う必要はないと仮定するのは論理的です (私は推測します)。Thread.join()スレッドがすでに終了している場合に死ぬだけではない と比較してください。

  2. プロセスを強制終了する唯一の方法は、プロセスにシグナルを送ることです。一部の OS では、他のより「暴力的な」方法があります (たとえば、一部のプラットフォームでは、OS の実行中のプロセスのリストからプロセスを単純に削除することができます。結果は未定義であり、通常は醜い結果になります)。私が知っているプラ​​ットフォームでは、シグナルを送信することがすべてです。

  3. 確かに、呼び出しに時間がかかるためである可能性がありThread.sleep()ます。タイムアウト値を増やしてみてください。

于 2012-12-20T13:17:30.167 に答える