使用Java杀死进程
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Java杀死进程相关的知识,希望对你有一定的参考价值。
我想知道如何“杀死”一个已启动的进程。我知道Process API,但我不确定,如果我可以使用它来“杀死”已经运行的进程,例如firefox.exe等。如果可以使用Process API,请指点我进入正确的方向?如果没有,其他可用选项有哪些?谢谢。
如果您在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表示错误)。但这当然会使您的应用程序平台依赖。
在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上做同样的事情似乎也会使进程变得很好(但这可能是由于Windows没有使用信号来破坏)。
其实我发现Java - Process.destroy() source code for Linux相关的线程和openjava实现似乎也使用-TERM,这似乎非常错误。
试试吧:
String command = "killall <your_proccess>";
Process p = Runtime.getRuntime().exec(command);
p.destroy();
如果进程仍然存在,请添加:
p.destroyForcibly();
使用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
。 - 查找满足过滤条件的第一个过滤过程。
- 如果至少有一个进程'命令行包含“firefox”,那么使用
destroy
杀死它。
没有必要进口,因为ProcessHandle
是java.lang
的一部分。
您可以通过调用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();
以上是关于使用Java杀死进程的主要内容,如果未能解决你的问题,请参考以下文章