How to exec external commands in Java with correct parameters

By Steve Claridge on 2021-11-06.

Java offers a simple API for executing external applications, but it's easy to use it wrong and run into problems. Here's how to correctly exec things with the right parameters.

Command won't execute when there are spaces in the parameters

Basic usage of Java's Runtime API to execute a command-line app called helloworld looks like this

Process process = Runtime.getRuntime().exec("helloworld");
int exitCode = process.waitFor();
System.out.println(exitCode);

Lets imagine the helloworld application is a command-line tool that takes a few parameters, does some stuff with them and prints a result. In the above example with are not passing any parameters. That will work fine, so now we add a couple of params to the application we are executing, this will also work

Process process = Runtime.getRuntime().exec("helloworld param1 param2");
int exitCode = process.waitFor();
System.out.println(exitCode);

All good, now the problems start when we want to send a parameter of Mickey Mouse and to do that on the command line we'd put double-quotes around it to make sure the application treats its as one parameter, our code is now

Process process = Runtime.getRuntime().exec("helloworld \"Mickey Mouse\" param2");
int exitCode = process.waitFor();
System.out.println(exitCode);

This will not work as expected, it will not execute helloworld "Mickey Mouse" param2. I.e. it won't call helloworld with two parameters, it will have three. The spaces in the parameters break the exec() method as it's not smart and doesn't treat anything in double quotes as one parameter.

The getRuntime().exec() uses StringTokenizer() to to parse the given string and its default behaviour is to split upon a space, in other words, every space-separated word is treated as a parameter and double-quotes are ignored. So the above code executes helloworld with three parameters, which are "Mickey and Mouse" and param2.

How to correctly execute a command with spaces in the parameters?

Split it yourself and pass an array of strings to the exec() command instead of getting exec() to do the split. You do not need to add in double-quotes in this method as the exec knows that each array element is a param, regardless of whether it contains spaces or not.

var strings = new String[]{"helloworld", "Mickey Mouse", "param2"};
Process process = Runtime.getRuntime().exec(strings);