web-dev-qa-db-fra.com

Tuer un processus en utilisant Java

Je voudrais savoir comment "tuer" un processus qui a démarré. Je suis au courant de l'API Process, mais je ne suis pas sûr. Si je peux l'utiliser pour "tuer" un processus déjà en cours d'exécution, tel que firefox.exe, etc. Si l'API Process peut être utilisée, pouvez-vous m'indiquer le direction correcte? Si non, quelles sont les autres options disponibles? Merci.

60
Jeel Shah

Si vous démarrez le processus depuis dans votre application Java (par exemple, en appelant Runtime.exec() ou ProcessBuilder.start()), vous disposez d'une référence Process valide et vous pouvez appeler la méthode destroy() dans la classe Process pour tuer ce processus particulier. 

Sachez toutefois que si le processus que vous appelez crée de nouveaux sous-processus, ceux-ci ne peuvent pas être terminés (voir http://bugs.Sun.com/bugdatabase/view_bug.do?bug_id=4770092 ).

D'autre part, si vous souhaitez supprimer des processus externes (que vous n'avez pas créés depuis votre application Java), vous pouvez alors 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 renvoyées pour vous assurer que l'application a été supprimée ou non (0 signifie succès, -1 signifie erreur). Mais cela va bien sûr rendre votre plate-forme applicative dépendante.

51
Yohan Liyanage

Sous Windows, vous pouvez utiliser cette commande 

taskkill /F /IM <processname>.exe 

pour le tuer avec force. Alors il sera

Runtime.getRuntime().exec("taskkill /F /IM <processname>.exe")
56

AFAIU Java.lang.Process est le processus créé par Java lui-même (comme Runtime.exec ('firefox'))

Vous pouvez utiliser des commandes dépendant du système telles que 

 Runtime rt = Runtime.getRuntime();
  if (System.getProperty("os.name").toLowerCase().indexOf("windows") > -1) 
     rt.exec("taskkill " +....);
   else
     rt.exec("kill -9 " +....);
30
chro

Je suis tombé par hasard sur un autre moyen de tuer par force Unix (pour ceux qui utilisent Weblogic). C’est moins cher et plus élégant que de lancer/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 avez du mal à obtenir le pid, vous pouvez utiliser la réflexion sur Java.lang.UNIXProcess , par exemple:

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);
}
4
chukko

Il s’agit peut-être d’un défaut d’interpréteur Java, mais Java sur HPUX ne fait pas kill -9, mais seulement kill -TERM.

J'ai fait un petit test testDestroy.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 10 ans (pas tué après 1 comme prévu) et montre:

...
[19999]   Received signal 15, SIGTERM, in waitpid(), [caught], no siginfo
[19998] kill(19999, SIGTERM) ............................................................................. = 0
...

Faire la même chose sur Windows semble tuer le processus, même si le signal est traité (mais cela peut être dû au fait que Windows n'utilise pas de signaux pour détruire).

En fait, j'ai trouvé Java - Le code source de Process.destroy () pour Linux la mise en oeuvre de threads et d'openjava semble également utiliser -TERM, ce qui semble très faux.

3
chukko

Essayez le:

String command = "killall <your_proccess>";
Process p = Runtime.getRuntime().exec(command);
p.destroy();

si le processus est toujours en cours, ajoutez:

p.destroyForcibly();
2
Haysa Rodrigues

Avec Java 9, nous pouvons utiliser ProcessHandle 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 processus à tuer.

Ce:

  • Tout d’abord répertorie tous les processus en cours d’exécution sur le système en tant que Stream<ProcessHandle>

  • Lazily filtre ce flux pour ne conserver que les processus dont la ligne de commande lancée contient "firefox". commandLine ou command peuvent être utilisés en fonction de la façon dont nous voulons récupérer le processus.

  • Trouve le premier processus filtré répondant à la condition de filtrage.

  • Et si au moins une ligne de commande du processus contenait "firefox", la tue avec destroy.

Aucune importation nécessaire car ProcessHandle fait partie de Java.lang.

1
Xavier Guihot

Vous pouvez tuer un processus Windows (SIGTERM) démarré à partir de Java en appelant la méthode destroy sur l'objet Process. Vous pouvez également tuer tous les processus enfants (depuis Java 9). 

Le code suivant démarre un fichier de commandes, attend dix secondes, puis supprime tous les sous-processus et finalement le processus de traitement par lots 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();
0
Jamie Lister