Ich würde gerne wissen, wie man einen Prozess "tötet", der gestartet wurde. Ich kenne die Prozess-API, bin mir aber nicht sicher, ob ich damit einen bereits ausgeführten Prozess wie Firefox.exe usw. "beenden" kann. Wenn die Prozess-API verwendet werden kann, können Sie mich bitte auf die verweisen richtige Richtung? Wenn nicht, welche anderen Optionen stehen zur Verfügung? Vielen Dank.
71
Antworten:
Wenn Sie den Prozess mit in Ihrer Java-Anwendung starten (z. B. durch Aufrufen von
Runtime.exec()
oderProcessBuilder.start()
), haben Sie einen gültigenProcess
Verweis darauf und können diedestroy()
Methode in aufrufenProcess
Klasse , um diesen bestimmten Prozess abzubrechen.Beachten Sie jedoch, dass der von Ihnen aufgerufene Prozess möglicherweise nicht beendet wird, wenn neue Unterprozesse erstellt werden (siehe http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4770092) ).
Wenn Sie jedoch externe Prozesse beenden möchten (die Sie nicht aus Ihrer Java-App erstellt haben), können Sie auch O / S-Dienstprogramme aufrufen, mit denen Sie dies tun können. Sie können beispielsweise unter Unix / Linux einen Befehl
Runtime.exec()
on versuchenkill
und nach Rückgabewerten suchen , um sicherzustellen, dass die Anwendung beendet wurde oder nicht (0 bedeutet Erfolg, -1 bedeutet Fehler). Aber das macht Ihre Anwendungsplattform natürlich abhängig.quelle
Unter Windows können Sie diesen Befehl verwenden.
Um es gewaltsam zu töten, können Sie verwenden;
Runtime.getRuntime().exec("taskkill /F /IM <processname>.exe")
quelle
AFAIU java.lang.Process ist der von Java selbst erstellte Prozess (wie Runtime.exec ('Firefox')).
Sie können systemabhängige Befehle wie verwenden
Runtime rt = Runtime.getRuntime(); if (System.getProperty("os.name").toLowerCase().indexOf("windows") > -1) rt.exec("taskkill " +....); else rt.exec("kill -9 " +....);
quelle
Mit
Java 9
können wir ProcessHandle verwenden, mit dem sich native Prozesse leichter identifizieren und steuern lassen:ProcessHandle .allProcesses() .filter(p -> p.info().commandLine().map(c -> c.contains("firefox")).orElse(false)) .findFirst() .ifPresent(ProcessHandle::destroy)
wo "Firefox" ist der Prozess zu töten.
Diese:
Listet zunächst alle auf dem System ausgeführten Prozesse als auf
Stream<ProcessHandle>
Filtert diesen Stream faul, um nur Prozesse zu behalten, deren gestartete Befehlszeile "Firefox" enthält. Beide
commandLine
odercommand
können verwendet werden, je nachdem, wie der Prozess abgerufen werden soll.Findet den ersten gefilterten Prozess, der die Filterbedingung erfüllt.
Und wenn mindestens eine Prozessbefehlszeile "Firefox" enthielt, wird sie mit beendet
destroy
.Kein Import erforderlich, da
ProcessHandle
ein Teil vonjava.lang
.quelle
Aus Versehen bin ich auf eine andere Möglichkeit gestoßen, einen Force-Kill unter Unix durchzuführen (für diejenigen, die Weblogic verwenden). Dies ist billiger und eleganter als das Ausführen von / bin / kill -9 über Runtime.exec () .
import weblogic.nodemanager.util.Platform; import weblogic.nodemanager.util.ProcessControl; ... ProcessControl pctl = Platform.getProcessControl(); pctl.killProcess(pid);
Und wenn Sie Schwierigkeiten haben, die PID zu erhalten, können Sie die Reflexion auf java.lang.UNIXProcess verwenden , z.
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); }
quelle
Es könnte ein Java-Interpreter-Defekt sein, aber Java unter HPUX führt keinen Kill -9 aus, sondern nur einen Kill -TERM.
Ich habe einen kleinen Test gemacht testDestroy.java:
ProcessBuilder pb = new ProcessBuilder(args); Process process = pb.start(); Thread.sleep(1000); process.destroy(); process.waitFor();
Und die Anrufung:
$ tusc -f -p -s signal,kill -e /opt/java1.5/bin/java testDestroy sh -c 'trap "echo TERM" TERM; sleep 10'
stirbt nach 10s (nicht wie erwartet nach 1s getötet) und zeigt:
... [19999] Received signal 15, SIGTERM, in waitpid(), [caught], no siginfo [19998] kill(19999, SIGTERM) ............................................................................. = 0 ...
Dasselbe unter Windows zu tun, scheint den Prozess auch dann zu beenden, wenn das Signal verarbeitet wird (dies kann jedoch daran liegen, dass Windows keine Signale zum Zerstören verwendet).
Eigentlich fand ich Java - Process.destroy () Quellcode für Linux- bezogene Thread- und Openjava-Implementierung scheint auch -TERM zu verwenden, was sehr falsch zu sein scheint.
quelle
destroyForcibly()
gesendetkill -9
?Versuch es:
String command = "killall <your_proccess>"; Process p = Runtime.getRuntime().exec(command); p.destroy();
Wenn der Prozess noch läuft, fügen Sie hinzu:
quelle
Runtime.exec
der Rückkehr wissen Sie nicht, wie weit derkillall
Prozess fortgeschritten ist, und töten dann sofort diekillall
, vielleicht bevor sie die Möglichkeit hatte, etwas zu tun. Stattdessendestroy
sollten Sie es lieberwaitFor()
und seinen Exit-Status überprüfen.Sie können einen (SIGTERM) Windows-Prozess beenden, der von Java aus gestartet wurde, indem Sie die destroy-Methode für das Process-Objekt aufrufen. Sie können auch alle untergeordneten Prozesse beenden (seit Java 9).
Der folgende Code startet eine Batch-Datei, wartet zehn Sekunden, beendet dann alle Unterprozesse und beendet schließlich den Batch-Prozess selbst.
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();
quelle