簡體   English   中英

使用Java殺死進程

[英]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”的進程。 可以使用commandLinecommand取決於我們想要如何檢索該過程。

  • 查找滿足過濾條件的第一個過濾過程。

  • 並且如果至少一個進程的命令行包含“ firefox”,則使用destroy殺死它。

不需要導入,因為ProcessHandlejava.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM