CodeGym /Cours /JAVA 25 SELF /ProcessBuilder — exécuter des processus externes

ProcessBuilder — exécuter des processus externes

JAVA 25 SELF
Niveau 61, Leçon 0
Disponible

1. Qu’est-ce qu’un processus dans l’OS et pourquoi les lancer depuis Java

Processus : de la JVM à bash et retour

Lorsque vous allumez votre ordinateur et ouvrez un navigateur, une messagerie ou un jeu — tout cela correspond à des processus distincts. Le système d’exploitation lance pour chaque programme son propre « mini‑monde » : il alloue de la mémoire, du temps processeur, autorise l’accès aux fichiers et au réseau. Ainsi, les programmes coexistent sans se gêner.

Un programme Java ne fait pas exception. Quand vous exécutez java MyApp, le système crée pour lui un processus séparé avec toutes les ressources nécessaires. À l’intérieur de celui‑ci, votre programme fonctionne : calcule, dessine, lit des fichiers — tout ce qu’il doit faire.

Mais parfois, Java ne suffit pas. Il peut être nécessaire de solliciter un autre programme — lancer un archiveur pour compresser des fichiers, appeler ffmpeg pour traiter une vidéo, ou simplement connaître la version de Java installée sur l’ordinateur. C’est cela le lancement d’un processus externe : Java dit au système « appelle‑moi cet utilitaire », puis récupère le résultat de son exécution.

En substance, c’est un moyen de rendre votre application plus flexible : combiner différents outils, automatiser des tâches répétitives ou intégrer votre logique aux processus système existants. Parfois, il est plus simple de confier une partie du travail à une commande externe que de réinventer la roue dans le code.

JVM vs processus externe

Processus JVM — votre programme s’exécutant dans la machine virtuelle Java.

Processus externe — n’importe quel autre programme : calculatrice, script Python, ligne de commande, voire une autre instance de Java.

2. La classe ProcessBuilder

Aux « temps anciens », Java lançait des processus via la méthode Runtime.getRuntime().exec(). Ce n’était ni le moyen le plus pratique ni le plus sûr — comme essayer d’enfoncer un clou avec un microscope. À partir de Java 5, la classe ProcessBuilder est apparue ; elle permet de créer, configurer et lancer des processus externes de manière plus souple et plus claire.

ProcessBuilder est une sorte de « constructeur » qui permet de définir à l’avance tous les paramètres du futur processus : commande, arguments, dossier de travail, variables d’environnement, etc.

Syntaxe : création d’un processus

ProcessBuilder pb = new ProcessBuilder("commande", "argument1", "argument2", ...);
  • Le premier argument — le nom de la commande (par exemple, "ls", "dir", "ping", "java").
  • Les autres — les paramètres de la commande.

Exemple : exécuter la commande ls (Linux/Mac) ou dir (Windows)

ProcessBuilder pb;
if (System.getProperty("os.name").toLowerCase().contains("win")) {
    pb = new ProcessBuilder("cmd.exe", "/c", "dir");
} else {
    pb = new ProcessBuilder("ls", "-l");
}

À propos, sous Windows, des commandes comme dir, copy, etc. ne sont pas des exécutables distincts, mais des commandes « intégrées » à l’interpréteur de commandes (cmd.exe). Il faut donc les lancer via cmd.exe /c ....

Exemple : lancer un processus simple

ProcessBuilder pb = new ProcessBuilder("echo", "Hello, Java!");

3. Configuration de l’environnement du processus

Passage des arguments. Les arguments de la commande sont transmis sous forme de chaînes distinctes :

ProcessBuilder pb = new ProcessBuilder("ping", "google.com");

Définir le répertoire de travail. Par défaut, le processus est lancé dans le même dossier que votre application. Mais vous pouvez spécifier explicitement un autre répertoire :

pb.directory(new java.io.File("/tmp"));      // Pour Linux/Mac
pb.directory(new java.io.File("C:\\Temp"));  // Pour Windows

Modifier les variables d’environnement. Chaque processus possède son propre ensemble de variables d’environnement. Vous pouvez en ajouter ou en modifier :

pb.environment().put("MY_VAR", "HelloFromJava");

Cela peut être utile si le processus externe attend certaines variables spécifiques.

4. Lancer un processus

Méthode start(). Une fois tout configuré, il est temps de lancer le processus :

Process process = pb.start();

La méthode start() renvoie un objet Process qui permet de piloter le programme lancé : lire sa sortie, écrire sur son entrée, le terminer, etc.

Gestion des exceptions. start() peut lever une IOException si la commande est introuvable, si les droits sont insuffisants ou en cas d’autre erreur de lancement.

Exemple :

try {
    Process process = pb.start();
    // On travaille avec le processus...
} catch (IOException e) {
    System.out.println("Erreur lors du lancement du processus : " + e.getMessage());
}

5. Pratique : lancer des commandes simples

Exemple 1 : afficher la liste des fichiers d’un dossier

import java.io.*;

public class ProcessDemo {
    public static void main(String[] args) {
        // Déterminer la commande selon l’OS
        ProcessBuilder pb;
        if (System.getProperty("os.name").toLowerCase().contains("win")) {
            pb = new ProcessBuilder("cmd.exe", "/c", "dir");
        } else {
            pb = new ProcessBuilder("ls", "-l");
        }

        try {
            Process process = pb.start();

            // Lire la sortie du processus (stdout)
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream())
            );
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }

            // Attendre la fin du processus
            int exitCode = process.waitFor();
            System.out.println("Processus terminé avec le code : " + exitCode);

        } catch (IOException | InterruptedException e) {
            System.out.println("Erreur : " + e.getMessage());
        }
    }
}

Que se passe-t-il ici ?

  • Nous déterminons l’OS — pour choisir la bonne commande.
  • Nous créons ProcessBuilder avec la commande appropriée.
  • Nous lançons le processus via start().
  • Nous lisons les lignes depuis le stdout du processus et les affichons à l’écran.
  • Nous attendons la fin du processus (waitFor()).
  • Nous affichons le code de retour (0 — succès, autre — erreur).

Exemple 2 : exécuter java -version

ProcessBuilder pb = new ProcessBuilder("java", "-version");
try {
    Process process = pb.start();

    // java -version écrit sur stderr, donc on lit getErrorStream()
    BufferedReader reader = new BufferedReader(
        new InputStreamReader(process.getErrorStream())
    );
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
    process.waitFor();
} catch (IOException | InterruptedException e) {
    e.printStackTrace();
}

Point important : Certaines commandes (par exemple, java -version) écrivent non pas sur la sortie standard (stdout), mais dans le flux d’erreurs (stderr). Il faut donc parfois lire process.getErrorStream().

6. Multiplateforme : différences entre Windows et Linux/Mac

  • Les commandes et leurs paramètres peuvent différer.
  • Les chemins de fichiers s’écrivent différemment (C:\Temp vs /tmp).
  • Certaines commandes (par exemple, ls, cat) n’existent que sur les systèmes de type Unix, et sous Windows elles sont remplacées par des équivalents (dir, type).
  • Sous Windows, les commandes intégrées ne se lancent qu’avec cmd.exe /c commande.

Exemple de détection de l’OS :

String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) {
    // Windows
} else if (os.contains("mac")) {
    // macOS
} else if (os.contains("nix") || os.contains("nux")) {
    // Linux
}

Conseil : Testez toujours vos programmes sur les OS cibles si vous visez la multiplateforme.

7. Tableau : méthodes et possibilités principales de ProcessBuilder

Méthode/champ Rôle Exemple d’utilisation
new ProcessBuilder(String...)
Créer un processus avec commande et arguments
new ProcessBuilder("ls", "-l")
.directory(File)
Définir le répertoire de travail
.directory(new File("/tmp"))
.environment()
Obtenir/modifier les variables d’environnement
.environment().put("VAR", "value")
.start()
Lancer le processus
Process p = pb.start()
Process.getInputStream()
Obtenir le stdout du processus
InputStream
Process.getErrorStream()
Obtenir le stderr du processus
InputStream
Process.getOutputStream()
Obtenir le stdin du processus
OutputStream
Process.waitFor()
Attendre la fin du processus
int code = p.waitFor()
Process.exitValue()
Obtenir le code de retour du processus
int code = p.exitValue()

8. Erreurs fréquentes lors du lancement de processus externes

Erreur n° 1 : commande introuvable. Si vous vous trompez dans le nom de la commande ou si elle est absente du système, vous obtiendrez une IOException : Cannot run program .... Par exemple, tenter d’exécuter ls sous Windows.

Erreur n° 2 : passage incorrect des arguments. Inutile de concaténer toute la commande dans une seule chaîne ! Correct : new ProcessBuilder("ping", "google.com"). Incorrect : new ProcessBuilder("ping google.com").

Erreur n° 3 : ignorer les différences entre OS. Une commande qui fonctionne très bien sous Linux peut ne pas exister sous Windows, et inversement. Vérifiez toujours l’OS et adaptez la commande.

Erreur n° 4 : sortie du processus non lue. Si vous ne lisez pas la sortie du processus, celui‑ci peut « se bloquer » à cause d’un tampon plein. Même si vous n’avez pas besoin de la sortie — lisez‑la et ignorez‑la, par exemple.

Erreur n° 5 : flux non fermés. Il faut fermer les flux du processus après utilisation afin d’éviter les fuites de ressources.

Erreur n° 6 : exceptions non gérées. Lancer un processus externe est risqué. Utilisez toujours try-catch et informez l’utilisateur des erreurs.

1
Mission
JAVA 25 SELF, niveau 61, leçon 0
Bloqué
Inspecteur système 🖥️
Inspecteur système 🖥️
1
Mission
JAVA 25 SELF, niveau 61, leçon 0
Bloqué
Explorateur numérique 📁
Explorateur numérique 📁
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION