🌐
Baeldung
baeldung.com › home › java › core java › guide to java.lang.process api
Guide to java.lang.Process API | Baeldung
June 10, 2025 - In this tutorial, we’re going ... Process API, in contrast to a shallower look into how to use Process to execute a shell command. The process that it refers to is an executing application.
🌐
Oracle
docs.oracle.com › en › java › javase › 11 › core › process-api1.html
6 Process API - Java
October 20, 2025 - The Process API consists of the classes and interfaces ProcessBuilder, Process, ProcessHandle, and ProcessHandle.Info.
🌐
Oracle
docs.oracle.com › javase › 8 › docs › api › java › lang › Process.html
Process (Java Platform SE 8 )
April 21, 2026 - Java™ Platform Standard Ed. 8 ... The ProcessBuilder.start() and Runtime.exec methods create a native process and return an instance of a subclass of Process that can be used to control the process and obtain information about it.
🌐
DEV Community
dev.to › sadiul_hakim › java-process-api-basics-aml
Java Process API Basics - DEV Community
September 24, 2025 - The Java Process API, available since Java 5 and significantly improved in Java 9, provides a standard way to interact with native operating system processes from within a Java application.
🌐
Clojure
clojure.github.io › clojure › branch-master › clojure.java.process-api.html
clojure.java.process - Clojure v1.13.0 API documentation
A process invocation API wrapping the Java process API. The primary function is 'start' which starts a process and handles the streams as directed. It returns the Process object. Use 'exit-ref' to wait for completion and receive the exit value, and ‘stdout', 'stderr', 'stdin' to access the process streams.
🌐
Tutorialspoint
tutorialspoint.com › home › java › java process api improvements
Java - Process API Improvements
February 13, 2026 - In Java 9 Process API which is responsible to control and manage operating system processes has been improved considerably. ProcessHandle Class now provides process's native process ID, start time, accumulated CPU time, arguments, command, user, ...
🌐
OpenJDK
openjdk.org › jeps › 102
JEP 102: Process API Updates
The java.lang.ProcessHandle class returns information about each process as provided by the operating system including process id, arguments, command, start time, etc.
🌐
Oracle
docs.oracle.com › javase › 9 › docs › api › java › lang › Process.html
Process (Java SE 9 & JDK 9 )
Returns a ProcessHandle for the Process. Process objects returned by ProcessBuilder.start() and Runtime.exec(java.lang.String) implement toHandle as the equivalent of ProcessHandle.of(pid) including the check for a SecurityManager and RuntimePermission("manageProcess").
🌐
Oracle
docs.oracle.com › javase › › 9 › core › process-api1.htm
4 Process API
The Process API lets you start, retrieve information about, and manage native operating system processes.
Find elsewhere
🌐
Oracle
docs.oracle.com › en › java › javase › 11 › docs › api › java.base › java › lang › Process.html
Process (Java SE 11 & JDK 11 )
January 20, 2026 - Returns a ProcessHandle for the Process. Process objects returned by ProcessBuilder.start() and Runtime.exec(java.lang.String) implement toHandle as the equivalent of ProcessHandle.of(pid) including the check for a SecurityManager and RuntimePermission("manageProcess").
🌐
GeeksforGeeks
geeksforgeeks.org › java › process-api-updates-in-java
Process API Updates in Java - GeeksforGeeks
February 23, 2022 - Suppose if we want the process id of current running process, or we want to create a new process, or want to destroy already running process, or want to find the child and parent processes of current running process, or if we want to get any information regarding a process, then we can use Process API updates. Java 9 Process API Updates: -
🌐
Oracle
docs.oracle.com › javase › 7 › docs › api › java › lang › Process.html
Process (Java Platform SE 7 )
Java™ Platform Standard Ed. 7 ... The ProcessBuilder.start() and Runtime.exec methods create a native process and return an instance of a subclass of Process that can be used to control the process and obtain information about it.
🌐
Baeldung
baeldung.com › home › java › core java › guide to java.lang.processbuilder api
Guide to java.lang.ProcessBuilder API | Baeldung
November 26, 2025 - The Process API provides a powerful way to execute operating system commands in Java.
🌐
Java2Blog
java2blog.com › home › core java › java 9 › java 9 – process api improvements
Java 9 - Process API Improvements - Java2Blog
January 11, 2021 - ProcessHandle.Info Interface Methods Java improved its Process API in Java 9 version that includes new methods for Process class and two new interfaces ProcessHandle and ProcessHandle.Info. These methods are used to create a new process and get process information like process status, running time, process id, etc.
🌐
Oracle
docs.oracle.com › en › java › javase › 17 › docs › api › java.base › java › lang › Process.html
Process (Java SE 17 & JDK 17)
October 20, 2025 - Returns a ProcessHandle for the Process. Process objects returned by ProcessBuilder.start() and Runtime.exec(java.lang.String) implement toHandle as the equivalent of ProcessHandle.of(pid) including the check for a SecurityManager and RuntimePermission("manageProcess").
Top answer
1 of 2
3

You call exec(String), which in turn calls exec(String,String,File), which in turn uses a StringTokenizer to chop the command line passed as a single string into an argument list, and then calls exec(String[],String,File).

However, that tokenizer just chops at spaces (it doesn't know that it's working with a command line or what shell would be involved). That means you end up with these tokens as the command: bash, -c, 'echo, foo' --- note the single quotes; Runtime.exec does not involve a shell to handle quotes (or variable substitution or such).

bash then complains about the 'echo, but you don't see that cause you only print the child process' stdout, but not stderr. Add code like this to run:

Copybr = new BufferedReader(new InputStreamReader(p.getErrorStream()));
System.out.println("stderr:");
br.lines().forEach(System.out::println);

This gets me:

stderr:
bar': -c: line 1: unexpected EOF while looking for matching `''
bar': -c: line 2: syntax error: unexpected end of file

Now if you remove the single quotes from the call, you just get a single empty line because bash -c expects only one argument to run, which here is the echo, which prints a new line.

To fix this, you need to call the exec version that takes a String[] directly so that you control what is one argument:

Copyimport java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        run("echo", "foo");
        run("bash", "-c", "echo bar");
    }

    public static void run(String... command) throws IOException, InterruptedException {
        Process p = Runtime.getRuntime().exec(command);
        p.waitFor();
        var br = new BufferedReader(new InputStreamReader(p.getInputStream()));
        System.out.println("stdout:");
        br.lines().forEach(System.out::println);
 
        br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
        System.out.println("stderr:");
        br.lines().forEach(System.out::println);
    }
}
2 of 2
1

Personally, I'd use something higher level like the standard ProcessBuilder class or the exec library from Apache Commons instead, as they have better support for building complicated commands to execute:

Copyimport java.io.IOException;
import org.apache.commons.exec.*;

public class ExecDemo {
    // Build and execute a command with Apache Commons Exec
    private static void demoApacheExec()
        throws IOException, ExecuteException {
        var cmd = new CommandLine("sh");
        cmd.addArgument("-c");
        cmd.addArgument("echo test 1", false);
        System.out.println("Command: " + cmd);

        var executor = new DefaultExecutor();
        executor.execute(cmd);
    }

    // Build and execute a command with ProcessBuilder
    private static void demoProcessBuilder()
        throws IOException, InterruptedException {
        // Can also take a List<String> of arguments
        var pb = new ProcessBuilder("sh", "-c", "echo test 2").inheritIO();
        System.out.println("Command: " + pb.command());

        pb.start().waitFor();
    }

    public static void main(String[] args) {
        try {
            demoApacheExec();
            demoProcessBuilder();
        } catch (Exception e) {
            System.err.println("Error executing program: " + e);
            System.exit(1);
        }
    }
}

The important thing is making each argument its own separate thing instead of relying on trying to parse a single string like a shell would (A.C.E has a CommandLine.parse() function, but even it has issues with quoting; addArgument likes to put actual quotes around arguments with spaces in them when it doesn't actually need to unless you tell it not to.).

🌐
InfoWorld
infoworld.com › home › software development › java 9's other new enhancements, part 3: the process api
Java 9’s other new enhancements, Part 3: The Process API | InfoWorld
March 4, 2017 - ProcessHandle‘s allProcesses() method returns a Java 8 Streams API stream of process handles describing all processes visible to the current process (that is, the process invoking allProcesses()).