Execing Processes in Java

Here’s the translation of the Go code to Java, with explanations in Markdown format suitable for Hugo:

In the previous example, we looked at spawning external processes. We do this when we need an external process accessible to a running Java process. Sometimes we just want to completely replace the current Java process with another (perhaps non-Java) one. To do this, we’ll use Java’s implementation of the classic exec function.

import java.io.IOException;

public class ExecingProcesses {
    public static void main(String[] args) {
        // For our example we'll exec `ls`. Java doesn't require an
        // absolute path to the binary we want to execute, so we can
        // use the command name directly.
        String[] command = {"ls", "-a", "-l", "-h"};

        // ProcessBuilder is used to create operating system processes
        ProcessBuilder processBuilder = new ProcessBuilder(command);
        
        // Set the environment variables for the new process
        // Here we just use the current environment
        processBuilder.environment().putAll(System.getenv());

        try {
            // Start the process. This replaces the current Java process
            // with the new process (in this case, `ls`)
            Process process = processBuilder.inheritIO().start();
            
            // Wait for the process to complete
            int exitCode = process.waitFor();
            
            // If we reach here, it means the process has completed
            // and control has returned to our Java program
            System.out.println("Process exited with code " + exitCode);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

When we run our program, it will execute ls and then return control to our Java program:

$ javac ExecingProcesses.java
$ java ExecingProcesses
total 16
drwxr-xr-x  4 mark 136B Oct 3 16:29 .
drwxr-xr-x 91 mark 3.0K Oct 3 12:50 ..
-rw-r--r--  1 mark 1.3K Oct 3 16:28 ExecingProcesses.java
Process exited with code 0

Note that Java doesn’t offer a direct equivalent to the Unix fork function. However, Java’s ProcessBuilder and Runtime.exec() methods, along with its threading capabilities, cover most use cases for process creation and management.

In this Java implementation, we use ProcessBuilder to create and start a new process. The inheritIO() method is used to redirect the input, output, and error streams of the new process to the same as the current Java process. This allows us to see the output of the ls command.

Unlike the Go example, the Java process doesn’t completely replace itself with the new process. Instead, it starts the new process, waits for it to complete, and then continues execution. This is why we see the “Process exited with code 0” message at the end.