CodeGym /Courses /JAVA 25 SELF /ProcessBuilder — Launching External Processes

ProcessBuilder — Launching External Processes

JAVA 25 SELF
Level 61 , Lesson 0
Available

1. What OS processes are and why launch them from Java

Processes: from the JVM to bash and back

When you turn on your computer and open a browser, messenger, or game — each of these is a separate process. The operating system starts a dedicated “mini-world” for every program: it allocates memory and CPU time, and grants permissions to work with files and the network. This lets programs live side by side without getting in each other’s way.

A Java application is no exception. When you run java MyApp, the system creates a separate process for it with all the necessary resources. Your program then runs inside it: computing, drawing, reading files — everything it’s supposed to do.

But sometimes Java alone isn’t enough. You may need to ask another program for help — launch an archiver to package files, call ffmpeg to process video, or simply find out which Java version is installed on the machine. That’s what launching an external process is: Java tells the system “run this utility for me,” then receives its output.

In essence, it’s a way to make your application more flexible: combine different tools, automate routine tasks, or integrate your logic with existing system processes. Sometimes it’s easier to ask an external command to do part of the job than to reinvent the wheel in code.

JVM vs. external process

JVM process — your program running on the Java Virtual Machine.

External process — any other program: a calculator, a Python script, a command line, even another Java instance.

2. The ProcessBuilder class

In the “old” days, Java launched processes via Runtime.getRuntime().exec(). It wasn’t the most convenient or safest way — like trying to hammer a nail with a microscope. Starting with Java 5, the ProcessBuilder class appeared, which lets you create, configure, and launch external processes in a more flexible and understandable way.

ProcessBuilder is a “builder” that lets you predefine all the parameters of the future process: the command, arguments, working directory, environment variables, etc.

Syntax: creating a process

ProcessBuilder pb = new ProcessBuilder("command", "arg1", "arg2", ...);
  • The first argument is the command name (for example, "ls", "dir", "ping", "java").
  • The rest are the command’s parameters.

Example: run ls (Linux/Mac) or 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");
}

By the way, on Windows, commands like dir, copy, etc. aren’t separate executables — they’re commands built into the command prompt (cmd.exe). That’s why you need to run them via cmd.exe /c ....

Example: launching a simple process

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

3. Configuring the process environment

Passing arguments. Command arguments are passed as separate strings:

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

Setting the working directory. By default, the process starts in the same directory as your program. But you can explicitly set another directory:

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

Modifying environment variables. Each process has its own set of environment variables. You can add or change them:

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

This can be useful if the external process expects specific variables.

4. Starting a process

The start() method. When you’ve configured everything, it’s time to start the process:

Process process = pb.start();

The start() method returns a Process object that lets you control the launched program: read its output, write to its input, terminate it, and so on.

Exception handling. start() can throw an IOException if the command is not found, permissions are missing, or another startup error occurs.

Example:

try {
    Process process = pb.start();
    // Working with the process...
} catch (IOException e) {
    System.out.println("Failed to start process: " + e.getMessage());
}

5. Practice: running simple commands

Example 1: list files in a directory

import java.io.*;

public class ProcessDemo {
    public static void main(String[] args) {
        // Determine the command depending on the 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();

            // Read the process output (stdout)
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream())
            );
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }

            // Wait for the process to finish
            int exitCode = process.waitFor();
            System.out.println("Process exited with code: " + exitCode);

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

What’s happening here?

  • Detect the OS to choose the right command.
  • Create a ProcessBuilder with the desired command.
  • Start the process via start().
  • Read lines from the process stdout and print them.
  • Wait for the process to finish (waitFor()).
  • Print the exit code (0 — success, anything else — error).

Example 2: running java -version

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

    // java -version writes to stderr, so we read 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();
}

Important nuance: Some commands (for example, java -version) output information not to standard output (stdout) but to the error stream (stderr). So sometimes you need to read process.getErrorStream().

6. Cross-platform differences: Windows vs Linux/Mac

  • Commands and their parameters may differ.
  • File paths are written differently (C:\Temp vs /tmp).
  • Some commands (such as ls, cat) exist only on Unix-like systems; Windows has analogues (dir, type).
  • On Windows, built-in commands are launched only via cmd.exe /c command.

Example OS check:

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
}

Tip: Always test your programs on the target OSes if you’re aiming for cross-platform support.

7. Table: key ProcessBuilder methods and features

Method/field Purpose Usage example
new ProcessBuilder(String...)
Create a process with a command and arguments
new ProcessBuilder("ls", "-l")
.directory(File)
Set the working directory
.directory(new File("/tmp"))
.environment()
Get/modify environment variables
.environment().put("VAR", "value")
.start()
Start the process
Process p = pb.start()
Process.getInputStream()
Get process stdout
InputStream
Process.getErrorStream()
Get process stderr
InputStream
Process.getOutputStream()
Get process stdin
OutputStream
Process.waitFor()
Wait for the process to finish
int code = p.waitFor()
Process.exitValue()
Get the process exit code
int code = p.exitValue()

8. Common mistakes when launching external processes

Error #1: Command not found. If you misspell the command or it isn’t installed, you’ll get an IOException: Cannot run program .... For example, trying to run ls on Windows.

Error #2: Incorrect argument passing. Don’t concatenate the entire command into one string! Correct: new ProcessBuilder("ping", "google.com"). Incorrect: new ProcessBuilder("ping google.com").

Error #3: Ignoring OS differences. A command that works great on Linux may not exist on Windows, and vice versa. Always detect the OS and adapt the command.

Error #4: Not handling process output. If you don’t read the process output, it may “hang” due to buffer overflow. Even if you don’t plan to use the output — read it and, for example, just discard it.

Error #5: Not closing streams. You need to close the process streams after use to avoid resource leaks.

Error #6: Not handling exceptions. Launching an external process is risky. Always use try-catch and inform the user about errors.

1
Task
JAVA 25 SELF, level 61, lesson 0
Locked
System Inspector 🖥️
System Inspector 🖥️
1
Task
JAVA 25 SELF, level 61, lesson 0
Locked
Digital Pathfinder 📁
Digital Pathfinder 📁
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION