別のJavaアプリケーションを起動するJavaアプリケーションがあります。ランチャーにはウォッチドッグタイマーがあり、2番目のVMから定期的に通知を受け取ります。ただし、通知が受信されない場合は、2番目の仮想マシンを強制終了し、ランチャーが追加のクリーンアップアクティビティを実行します。
問題は、Javaのみを使用してこれを行う方法はありますか?これまでのところ、この操作を実行するにはいくつかのネイティブメソッドを使用する必要があり、それはどういうわけか醜いです。
ありがとう!
別のJavaアプリケーションを起動するJavaアプリケーションがあります。ランチャーにはウォッチドッグタイマーがあり、2番目のVMから定期的に通知を受け取ります。ただし、通知が受信されない場合は、2番目の仮想マシンを強制終了し、ランチャーが追加のクリーンアップアクティビティを実行します。
問題は、Javaのみを使用してこれを行う方法はありますか?これまでのところ、この操作を実行するにはいくつかのネイティブメソッドを使用する必要があり、それはどういうわけか醜いです。
ありがとう!
何か不足しているかもしれませんが、返されたオブジェクトのdestroy()
メソッドを呼び出すことはできませんか?Process
Runtime.exec()
java.lang.Processを使用して、必要なことを行うことができます。ネストされたプロセスを作成し、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
}
お役に立てれば、
ショーン
これを行う通常の方法はProcess.destroy()
... を呼び出すことですが、* nix で sun JVM を使用する場合、プロセスを終了することが保証されていない SIGTERM にマップを破棄するため、これは不完全な解決策です (そのためには SIGKILL も必要です)。最終的な結果として、Java を使用して実際のプロセス管理を行うことはできません。
この問題に関する未解決のバグがいくつかあります。 リンク テキストを参照してください。
System.exit() を呼び出す 2 番目の JVM で (バーラップ、ヘシアンなどを介して) サービスを公開し、ウォッチドッグ JVM からそれを使用することもできます。2 番目の JVM が定期的な通知の送信を停止したときにのみシャットダウンする場合は、サービス呼び出しに応答する状態にない可能性があります。
おそらく、java.lang.Runtime.exec() を使用してシェル コマンドを呼び出すのが最善の方法です。
OK要点のひねりは次のとおりです。
Process API を使用して 2 番目の仮想マシンを閉じていましたが、うまくいきませんでした。
その理由は、2 つ目のアプリケーションが Eclipse RCP アプリケーションであり、付属の eclipse.exe ランチャーを使用して起動したためです。
ただし、これは、プロセス API の destroy() メソッドが eclipse.exe プロセスをターゲットにすることを意味します。このプロセスを強制終了すると、Java プロセスは無傷のままになります。そこで、ここにいる私の同僚の 1 人が、適切なアプリケーションを強制終了する小さなアプリケーションを作成しました。
したがって、プロセス API を使用する (そして冗長な中間ステップを削除する) ための解決策の 1 つは、Eclipse ランチャーを使用せずに、最初の仮想マシンにすべての機能を複製させることです。
私は仕事に行かなければならないと思います。
java.lang.Process
プロセスがwaitFor()
終了するのを待つdestroy()
メソッドと、サブプロセスを強制終了するメソッドがあります。
java.lang.Runtime.exec
それとシェルコマンドを実行できるはずです。
Java コードで実行時にプラットフォームを検出し、プラットフォームの kill プロセス コマンドを起動することができます。これは、実際に現在のソリューションを改良したものです。
ProcessBuilder APIを使用している場合は、Process.destroy ()もあります。
正確にはプロセス管理ではありませんが、起動している Java 仮想マシンで rmi サーバーを起動し、必要なクリーンアップを実行して System.exit() を呼び出すメソッドにリモートインスタンスをバインドできます。最初の vm は、そのリモート メソッドを呼び出して 2 番目の vm をシャットダウンできます。