起動したプロセスを「殺す」方法を知りたい。私はProcess APIを知っていますが、それを使用してfirefox.exeなどの既に実行中のプロセスを「殺す」ことができるかどうかはわかりません。ProcessAPIを使用できる場合は、正しい方向?そうでない場合、他の利用可能なオプションは何ですか?ありがとう。
Javaアプリケーションで(たとえば、Runtime.exec()
またはProcessBuilder.start()
を呼び出して)からプロセスを開始すると、有効なProcess
参照があり、 Process
クラスのdestroy()
メソッドを呼び出して、その特定のプロセスを強制終了できます。
ただし、呼び出すプロセスが新しいサブプロセスを作成する場合、それらが終了しない場合があることに注意してください( http://bugs.Sun.com/bugdatabase/view_bug.do?bug_id=4770092 を参照) 。
一方、外部プロセス(Javaアプリから生成されていない)を強制終了する場合、できることの1つは、それを可能にするO/Sユーティリティを呼び出すことです。たとえば、Runtime.exec()
on kill
コマンドをUnix/Linuxで試して、戻り値をチェックして、アプリケーションが強制終了されたかどうかを確認できます(0は成功、-1はエラーを意味します)。しかし、それはもちろんあなたのアプリケーションプラットフォームを依存させます。
Windowsでは、このコマンドを使用できます。
taskkill /F /IM <processname>.exe
強制終了するには、次を使用できます。
Runtime.getRuntime().exec("taskkill /F /IM <processname>.exe")
AFAIU Java.lang.Processは、Java自体によって作成されたプロセスです(Runtime.exec( 'firefox')など)
次のようなシステム依存のコマンドを使用できます
Runtime rt = Runtime.getRuntime();
if (System.getProperty("os.name").toLowerCase().indexOf("windows") > -1)
rt.exec("taskkill " +....);
else
rt.exec("kill -9 " +....);
偶然、Unixで強制終了する別の方法を見つけました(Weblogicを使用している人向け)。これは、Runtime.exec()を使用して/ bin/kill -9を実行するよりも安価でエレガントです。
import weblogic.nodemanager.util.Platform;
import weblogic.nodemanager.util.ProcessControl;
...
ProcessControl pctl = Platform.getProcessControl();
pctl.killProcess(pid);
また、pidの取得に苦労する場合は、Java.lang.UNIXProcessでリフレクションを使用できます。例:
Process proc = Runtime.getRuntime().exec(cmdarray, envp);
if (proc instanceof UNIXProcess) {
Field f = proc.getClass().getDeclaredField("pid");
f.setAccessible(true);
int pid = f.get(proc);
}
Javaインタープリターの欠陥の可能性がありますが、HPUX上のJavaはkill -9ではなく、kill -TERMのみを実行します。
私は小さなテストtestDestroy.Javaを行いました:
ProcessBuilder pb = new ProcessBuilder(args);
Process process = pb.start();
Thread.sleep(1000);
process.destroy();
process.waitFor();
そして呼び出し:
$ tusc -f -p -s signal,kill -e /opt/Java1.5/bin/Java testDestroy sh -c 'trap "echo TERM" TERM; sleep 10'
10秒後に死亡し(予想どおり1秒後に殺されない)、以下を示します。
...
[19999] Received signal 15, SIGTERM, in waitpid(), [caught], no siginfo
[19998] kill(19999, SIGTERM) ............................................................................. = 0
...
Windowsで同じことを行うと、シグナルが処理されてもプロセスが正常に終了するようです(ただし、ウィンドウが破壊するためにシグナルを使用していないことが原因である可能性があります)。
実際、私は Java-LinuxのProcess.destroy()ソースコード 関連するスレッドとopenjava実装も-TERMを使用しているようで、非常に間違っているようです。
Java 9
では、 ProcessHandle を使用できます。これにより、ネイティブプロセスの識別と制御が容易になります。
ProcessHandle
.allProcesses()
.filter(p -> p.info().commandLine().map(c -> c.contains("firefox")).orElse(false))
.findFirst()
.ifPresent(ProcessHandle::destroy)
ここで、「firefox」は殺すプロセスです。
この:
最初に、システムで実行されているすべてのプロセスをStream<ProcessHandle>
としてリストします
このストリームを遅延フィルタリングして、起動されたコマンドラインに「firefox」が含まれるプロセスのみを保持します。プロセスの取得方法に応じて、commandLine
またはcommand
の両方を使用できます。
フィルタリング条件を満たす最初のフィルタリングされたプロセスを見つけます。
そして、少なくとも1つのプロセスのコマンドラインに「firefox」が含まれている場合、destroy
を使用してそれを強制終了します。
ProcessHandle
はJava.lang
の一部であるため、インポートは不要です。
それを試してみてください:
String command = "killall <your_proccess>";
Process p = Runtime.getRuntime().exec(command);
p.destroy();
プロセスがまだ生きている場合、追加します:
p.destroyForcibly();
Processオブジェクトでdestroyメソッドを呼び出すことにより、Javaから開始されたWindowsプロセス(SIGTERM)を強制終了できます。子プロセスを強制終了することもできます(Java 9以降)。
次のコードはバッチファイルを開始し、10秒間待機してからすべてのサブプロセスを強制終了し、最後にバッチプロセス自体を強制終了します。
ProcessBuilder pb = new ProcessBuilder("cmd /c my_script.bat"));
Process p = pb.start();
p.waitFor(10, TimeUnit.SECONDS);
p.descendants().forEach(ph -> {
ph.destroy();
});
p.destroy();