Tuer un processus en utilisant Java
je voudrais savoir comment" tuer " un processus qui a commencé. Je suis au courant de l'API de processus, mais je ne suis pas sûr, si je peux l'utiliser pour "tuer" un processus déjà en cours d'exécution, comme firefox.exe etc. Si L'API Process peut être utilisée, pouvez-vous m'indiquer la bonne direction? Si non, quelles sont les autres options disponibles? Grâce.
8 réponses
si vous démarrez le processus à partir de avec dans votre application Java (ex. en appelant Runtime.exec()
ou ProcessBuilder.start()
) alors vous avez une référence valide Process
, et vous pouvez invoquer la méthode destroy()
dans la classe Process
pour tuer ce processus particulier.
mais sachez que si le processus que vous invoquez crée de nouveaux sous-processus, ceux-ci ne peuvent pas être arrêtés (voir http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4770092 ).
d'un autre côté, si vous voulez tuer des processus externes (que vous n'avez pas générés depuis votre application Java), alors une chose que vous pouvez faire est d'appeler des utilitaires O/S qui vous permettent de le faire. Par exemple, vous pouvez essayer une commande Runtime.exec()
sur kill
sous Unix / Linux et vérifier les valeurs de retour pour s'assurer que l'application a été tuée ou non (0 signifie succès, -1 signifie erreur). Mais cela rendra bien sûr votre plate-forme d'application dépendante.
dans Windows vous devez probablement utiliser cette commande
taskkill /F /IM <processname>.exe
pour le tuer avec force. Il sera donc
Runtime.getRuntime().exec("taskkill /F /IM <processname>.exe")
AFAIU java.lang.Processus est le processus créé par java lui-même (comme Runtime.exec ("firefox"))
vous pouvez utiliser des commandes dépendant du système comme
Runtime rt = Runtime.getRuntime();
if (System.getProperty("os.name").toLowerCase().indexOf("windows") > -1)
rt.exec("taskkill " +....);
else
rt.exec("kill -9 " +....);
accidentellement je suis tombé sur une autre façon de faire un kill de force sur Unix (pour ceux qui utilisent Weblogic). C'est moins cher et plus élégant que running /bin/kill -9 via Runtime.exec () .
import weblogic.nodemanager.util.Platform;
import weblogic.nodemanager.util.ProcessControl;
...
ProcessControl pctl = Platform.getProcessControl();
pctl.killProcess(pid);
et si vous luttez pour obtenir le pid, vous pouvez utiliser la réflexion sur java.lang.UNIXProcess , p.ex.:
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);
}
c'est peut-être un défaut d'interpréteur java, mais java sur HPUX ne fait pas un kill -9, mais seulement un kill-TERM.
j'ai fait un petit test de Troy.java:
ProcessBuilder pb = new ProcessBuilder(args);
Process process = pb.start();
Thread.sleep(1000);
process.destroy();
process.waitFor();
et l'invocation:
$ tusc -f -p -s signal,kill -e /opt/java1.5/bin/java testDestroy sh -c 'trap "echo TERM" TERM; sleep 10'
meurt après 10s (pas tué après 1s comme prévu) et montre:
...
[19999] Received signal 15, SIGTERM, in waitpid(), [caught], no siginfo
[19998] kill(19999, SIGTERM) ............................................................................. = 0
...
Faire la même sur windows semble tuer le processus d'amende, même si le signal est traité (mais qui pourrait être due à windows pas en utilisant des signaux à détruire).
en fait j'ai trouvé Java - Process.destroy () code source pour Linux fil relatif et l'implémentation openjava semble utiliser-TERM aussi, ce qui semble très mal.
l'Essayer:
String command = "killall <your_proccess>";
Process p = Runtime.getRuntime().exec(command);
p.destroy();
si le procédé est encore vivant, ajouter:
p.destroyForcibly();
vous pouvez tuer un (SIGTERM) un processus windows qui a été démarré à partir de Java en appelant la méthode destroy sur L'objet Process. Vous pouvez également tuer tout processus enfant (depuis Java 9).
le code suivant démarre un fichier batch, attend dix secondes puis tue tous les sous-processus et finalement tue le processus batch lui-même.
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();
avec Java 9
, nous pouvons utiliser ProcessHandle ce qui facilite l'identification et le contrôle des processus natifs:
ProcessHandle
.allProcesses()
.filter(p -> p.info().commandLine().map(c -> c.contains("firefox")).orElse(false))
.findFirst()
.ifPresent(ProcessHandle::destroy)
où "firefox" est le procédé pour tuer.
:
-
Première liste tous les processus en cours d'exécution sur le système comme un
Stream<ProcessHandle>
-
filtre ce flux pour ne conserver que les processus dont la ligne de commande contient "firefox". Les deux
commandLine
oucommand
peuvent être utilisés selon la façon dont nous voulons récupérer le processus. -
trouve le premier procédé filtré satisfaisant à la condition de filtrage.
-
et si au moins une ligne de commande de processus contenait" firefox", le tue en utilisant
destroy
.
aucune importation nécessaire car ProcessHandle
fait partie de java.lang
.