別の仮想マシンから Java 仮想マシンを強制終了することはできますか?
-
09-06-2019 - |
質問
別の Java アプリケーションを起動する Java アプリケーションがあります。ランチャーにはウォッチドッグ タイマーがあり、2 番目の VM から定期的に通知を受け取ります。ただし、通知が受信されない場合は、2 番目の仮想マシンを強制終了する必要があり、ランチャーは追加のクリーンアップ アクティビティを実行します。
問題は、Java のみを使用してこれを行う方法はあるのかということです。これまでのところ、この操作を実行するにはいくつかのネイティブメソッドを使用する必要がありますが、それはどういうわけか醜いです。
ありがとう!
解決
何か見落としているかもしれませんが、電話してもらえませんか destroy()
のメソッド Process
によって返されるオブジェクト Runtime.exec()
?
他のヒント
使用できます java.lang.プロセス やりたいことをするために。ネストされたプロセスを作成し、Process インスタンスへの参照を取得したら、その標準出力ストリームとエラー ストリームへの参照を取得できます。これらを定期的に監視し、プロセスを閉じたい場合は .destroy() を呼び出すことができます。全体は次のようになります。
Process nestedProcess = new ProcessBuilder("java mysubprocess").start();
InputStream nestedStdOut = nestedProcess.getInputStream(); //kinda backwards, I know
InputStream nestedStdErr = nestedProcess.getErrorStream();
while (true) {
/*
TODO: read from the std out or std err (or get notifications some other way)
Then put the real "kill-me" logic here instead of if (false)
*/
if (false) {
nestedProcess.destroy();
//perform post-destruction cleanup here
return;
}
Thread.currentThread().sleep(1000L); //wait for a bit
}
お役に立てれば、
ショーン
System.exit() を呼び出す 2 番目の JVM 上で (バーラップ、ヘシアンなどを介して) サービスを公開し、それをウォッチドッグ JVM から消費することもできます。2 番目の JVM が定期的な通知の送信を停止したときにのみシャットダウンしたい場合は、サービス呼び出しに応答できる状態にない可能性があります。
java.lang.Runtime.exec() を使用してシェル コマンドを呼び出すのがおそらく最善の策です。
これを行う通常の方法は、Process.destroy()... を呼び出すことです。ただし、*nix で Sun JVM を使用する場合、SIGTERM 上にマップが破棄され、プロセスが終了することが保証されないため、これは不完全な解決策です (そのためには SIGKILL も必要です)。その結果、Java を使用して実際のプロセス管理を行うことはできなくなります。
この問題に関しては未解決のバグがいくつかあります。以下を参照してください。リンクテキスト
java.lang.Process には、プロセスが終了するのを待つ waitFor() メソッドと、サブプロセスを強制終了する destroy() メソッドがあります。
OK、要点は次のとおりです。
Process API を使用して 2 番目の仮想マシンを閉じていましたが、機能しませんでした。
その理由は、2 番目のアプリケーションが Eclipse RCP アプリケーションであり、含まれている eclipse.exe ランチャーを使用して起動したためです。
ただし、これは、プロセス API の destroy() メソッドが eclipse.exe プロセスをターゲットにすることを意味します。このプロセスを強制終了しても、Java プロセスは無傷のままになります。そこで、ここにいる私の同僚の 1 人が、適切なアプリケーションを強制終了する小さなアプリケーションを作成しました。
したがって、Process API を使用する (そして冗長な中間ステップを削除する) 解決策の 1 つは、Eclipse ランチャーを使用せずに、最初の仮想マシンにそのすべての機能を複製させることです。
仕事に行かなければならないと思います。
java.lang.Runtime.exec とシェルコマンドを実行できるはずです。
Java コードで実行時にプラットフォームを検出し、プラットフォームの kill process コマンドを起動することができます。これは実際には、現在のソリューションを改良したものです。
それもあります Process.destroy(), を使用している場合は、 プロセスビルダー API
正確にはプロセス管理ではありませんが、起動している Java 仮想マシンで rmi サーバーを起動し、 リモート 必要なクリーンアップを実行し、System.exit() を呼び出すメソッドを持つインスタンス。その後、最初の VM はそのリモート メソッドを呼び出して 2 番目の VM をシャットダウンできます。