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 |
|---|---|---|
|
Créer un processus avec commande et arguments | |
|
Définir le répertoire de travail | |
|
Obtenir/modifier les variables d’environnement | |
|
Lancer le processus | |
|
Obtenir le stdout du processus | |
|
Obtenir le stderr du processus | |
|
Obtenir le stdin du processus | |
|
Attendre la fin du processus | |
|
Obtenir le code de retour du processus | |
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.
GO TO FULL VERSION