我想知道如何“杀死”已经启动的过程。我知道Process API,但是不确定,是否可以使用它来杀死已经运行的进程,例如firefox.exe等。如果可以使用Process API,请您指向我正确的方向?如果没有,还有哪些其他可用选项?谢谢。
我想知道如何“杀死”已经启动的过程。我知道Process API,但是不确定,是否可以使用它来杀死已经运行的进程,例如firefox.exe等。如果可以使用Process API,请您指向我正确的方向?如果没有,还有哪些其他可用选项?谢谢。
Answers:
如果您是从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()
onkill
命令并检查返回值,以确保应用程序是否被杀死(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 " +....);
使用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
。
偶然地,我偶然发现了另一种在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未使用信号来销毁)。
实际上,我发现Linux相关线程的Java-Process.destroy()源代码和openjava实现似乎也都使用-TERM,这似乎非常错误。
destroyForcibly()
发送kill -9
吗?
试试看:
String command = "killall <your_proccess>";
Process p = Runtime.getRuntime().exec(command);
p.destroy();
如果该过程仍然存在,请添加:
p.destroyForcibly();
Runtime.exec
又回来了,你不知道多远killall
进程已取得进展,然后立即杀死killall
,也许收到了做任何事情的机会。而不是destroy
,您应该选择waitFor()
它并检查其退出状态。
您可以通过调用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();