使用Java杀死进程

问题描述 投票:61回答:8

我想知道如何“杀死”一个已启动的进程。我知道Process API,但我不确定,如果我可以使用它来“杀死”已经运行的进程,例如firefox.exe等。如果可以使用Process API,请指点我进入正确的方向?如果没有,其他可用选项有哪些?谢谢。

java process
8个回答
51
投票

如果您在Java应用程序中启动该过程(例如,通过调用Runtime.exec()ProcessBuilder.start()),那么您有一个有效的Process引用,并且您可以在destroy()类中调用Process方法来杀死该特定进程。

但请注意,如果您调用的进程创建新的子进程,则可能不会终止这些进程(请参阅http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4770092)。

另一方面,如果你想杀死外部进程(你没有从你的Java应用程序中产生),那么你可以做的一件事就是调用O / S实用程序来实现这一点。例如,您可以在Unix / Linux下的Runtime.exec()命令上尝试kill并检查返回值以确保应用程序被杀死(0表示成功,-1表示错误)。但这当然会使您的应用程序平台依赖。


56
投票

在Windows上,您可以使用此命令。

taskkill /F /IM <processname>.exe 

要强行杀死它,你可以使用;

Runtime.getRuntime().exec("taskkill /F /IM <processname>.exe")

30
投票

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 " +....);

4
投票

无意中我偶然发现了另一种在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);
}

3
投票

它可能是一个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上做同样的事情似乎也会使进程变得很好(但这可能是由于Windows没有使用信号来破坏)。

其实我发现Java - Process.destroy() source code for Linux相关的线程和openjava实现似乎也使用-TERM,这似乎非常错误。


2
投票

试试吧:

String command = "killall <your_proccess>";
Process p = Runtime.getRuntime().exec(command);
p.destroy();

如果进程仍然存在,请添加:

p.destroyForcibly();

1
投票

使用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”的进程。根据我们想要检索过程的方式,可以使用commandLinecommand
  • 查找满足过滤条件的第一个过滤过程。
  • 如果至少有一个进程'命令行包含“firefox”,那么使用destroy杀死它。

没有必要进口,因为ProcessHandlejava.lang的一部分。


0
投票

您可以通过调用Process对象上的destroy方法来终止(SIGTERM)从Java启动的Windows进程。您也可以杀死任何子进程(自Java 9起)。

以下代码启动批处理文件,等待十秒然后终止所有子进程,最后终止批处理过程。

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();
© www.soinside.com 2019 - 2024. All rights reserved.