Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between ProcessBuilder and Runtime.exec()

I'm trying to execute an external command from java code, but there's a difference I've noticed between Runtime.getRuntime().exec(...) and new ProcessBuilder(...).start().

When using Runtime:

Process p = Runtime.getRuntime().exec(installation_path +                                         uninstall_path +                                         uninstall_command +                                         uninstall_arguments); p.waitFor(); 

the exitValue is 0 and the command is terminated ok.

However, with ProcessBuilder:

Process p = (new ProcessBuilder(installation_path +                                      uninstall_path +                                  uninstall_command,                                  uninstall_arguments)).start(); p.waitFor(); 

the exit value is 1001 and the command terminates in the middle, although waitFor returns.

What should I do to fix the problem with ProcessBuilder?

like image 495
gal Avatar asked Jul 28 '11 08:07

gal


People also ask

What is runtime exec?

exec(String[] cmdarray, String[] envp) method executes the specified command and arguments in a separate process with the specified environment. This is a convenience method. An invocation of the form exec(cmdarray, envp) behaves in exactly the same way as the invocation exec(cmdarray, envp, null).

How does ProcessBuilder work?

Constructs a process builder with the specified operating system program and arguments. This is a convenience constructor that sets the process builder's command to a string list containing the same strings as the command array, in the same order.

How does runtime getRuntime exec work?

Runtime features a static method called getRuntime() , which retrieves the current Java Runtime Environment. That is the only way to obtain a reference to the Runtime object. With that reference, you can run external programs by invoking the Runtime class's exec() method.

Is ProcessBuilder thread safe?

ProcessBuilder is not thread safe, as stated in the javadoc.


1 Answers

The various overloads of Runtime.getRuntime().exec(...) take either an array of strings or a single string. The single-string overloads of exec() will tokenise the string into an array of arguments, before passing the string array onto one of the exec() overloads that takes a string array. The ProcessBuilder constructors, on the other hand, only take a varargs array of strings or a List of strings, where each string in the array or list is assumed to be an individual argument. Either way, the arguments obtained are then joined up into a string that is passed to the OS to execute.

So, for example, on Windows,

Runtime.getRuntime().exec("C:\DoStuff.exe -arg1 -arg2"); 

will run a DoStuff.exe program with the two given arguments. In this case, the command-line gets tokenised and put back together. However,

ProcessBuilder b = new ProcessBuilder("C:\DoStuff.exe -arg1 -arg2"); 

will fail, unless there happens to be a program whose name is DoStuff.exe -arg1 -arg2 in C:\. This is because there's no tokenisation: the command to run is assumed to have already been tokenised. Instead, you should use

ProcessBuilder b = new ProcessBuilder("C:\DoStuff.exe", "-arg1", "-arg2"); 

or alternatively

List<String> params = java.util.Arrays.asList("C:\DoStuff.exe", "-arg1", "-arg2"); ProcessBuilder b = new ProcessBuilder(params); 
like image 118
Luke Woodward Avatar answered Oct 13 '22 11:10

Luke Woodward