[英]Killing a process using Java
我想知道如何“殺死”已啟動的過程。 我知道Process API,但是不確定,是否可以使用它來殺死已經運行的進程,例如firefox.exe等。如果可以使用Process API,請您指向我正確的方向? 如果沒有,還有哪些其他可用選項? 謝謝。
在Windows上,您可以使用此命令。
taskkill /F /IM <processname>.exe
要強行殺死它,您可以使用;
Runtime.getRuntime().exec("taskkill /F /IM <processname>.exe")
如果您從Java應用程序中使用來啟動進程(例如,通過調用Runtime.exec()
或ProcessBuilder.start()
),那么您將對其具有有效的Process
引用,並且可以在Process
類中調用destroy()
方法殺死那個特定的過程。
但是請注意,如果您調用的流程創建了新的子流程,則這些子流程可能不會終止(請參見http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4770092 )。
另一方面,如果您想殺死外部進程(您不是從Java應用程序生成的),那么您可以做的一件事是調用允許您執行此操作的O / S實用程序。 例如,您可以在Unix / Linux下在kill
命令上嘗試Runtime.exec()
並檢查返回值,以確保應用程序是否被殺死(0表示成功,-1表示錯誤)。 但這當然會使您的應用程序平台依賴。
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解釋器缺陷,但是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,這似乎非常錯誤。
偶然我偶然發現了另一種在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 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
一部分。
試試吧:
String command = "killall <your_proccess>";
Process p = Runtime.getRuntime().exec(command);
p.destroy();
如果該過程仍然存在,請添加:
p.destroyForcibly();
您可以通過調用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();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.