When run, programs occupy their own processes. These are at the level of the operating system. And one process, in a Java program, cannot contain another one.
But with ProcessBuilder
, in java.lang.ProcessBuilder
, we construct and invoke operating system commands. We launch external processes—like EXEs.
This program creates an instance of ProcessBuilder
. It then calls command()
to set the command. We use two arguments: two strings.
string
.import java.io.IOException; import java.lang.ProcessBuilder; public class Program { public static void main(String[] args) throws IOException { // Create ProcessBuilder. ProcessBuilder p = new ProcessBuilder(); // Use command "notepad.exe" and open the file. p.command("notepad.exe", "C:\\file.txt"); p.start(); } }
In this example we invoke a specific executable at a known location on the computer. We concat a folder path and an executable name. Here I invoke photoshop.exe.
import java.io.IOException; import java.lang.ProcessBuilder; public class Program { public static void main(String[] args) throws IOException { String folder = "C:\\Program Files\\Adobe\\Adobe Photoshop CC\\"; String exe = "photoshop.exe"; // Create and start Process with ProcessBuilder. ProcessBuilder p = new ProcessBuilder(); p.command(folder + exe); p.start(); } }
RedirectOutput
This program uses the redirectOutput
method to have an executable program write to a file. It uses the 7-Zip EXE, a compression utility, and writes to "test.txt."
import java.io.File; import java.io.IOException; public class Program { public static void main(String[] args) throws IOException { // Create ProcessBuilder and target 7-Zip executable. ProcessBuilder b = new ProcessBuilder(); b.command("C:\\7za.exe"); // Redirect output to this file. b.redirectOutput(new File("C:\\folder\\test.txt")); b.start(); } }7-Zip (A) 9.07 beta Copyright (c) 1999-2009 Igor Pavlov 2009-08-29 Usage: 7za <command> [<switches>...] <archive_name> [<file_names>...] [<@listfiles...>]
ArrayList
, commandThe ProcessBuilder
class
supports an ArrayList
(or any List
) as an argument. We can separate parts of a command into an ArrayList
and then execute them.
import java.io.IOException; import java.util.ArrayList; public class Program { public static void main(String[] args) throws IOException { ProcessBuilder b = new ProcessBuilder(); // Create an ArrayList with two values. // ... This starts a specific browser, which is not ideal. ArrayList<String> values = new ArrayList<>(); values.add("C:\\Program Files\\Internet Explorer\\iexplore.exe"); values.add("http://en.wikipedia.org/"); // Pass List to command method. b.command(values); b.start(); } }
DestroyForcibly
Things in life do not always go our way. With destroyForcibly
we kill a process. This is sometimes needed if a process has finished or has frozen.
import java.io.IOException; import java.lang.ProcessBuilder; public class Program { public static void main(String[] args) throws IOException, InterruptedException { ProcessBuilder p = new ProcessBuilder(); p.command("notepad.exe"); // Start notepad. Process notepad = p.start(); System.out.println("Start"); // Sleep for 5 seconds. Thread.sleep(5000); // Kill notepad. notepad.destroyForcibly(); System.out.println("End"); } }Start End
IOException
As with file handling, launching processes is prone to failure. This is not our fault. But we must protect against it.
We can specify the method throws exceptions in its declaration. Alternatively we can handle the exceptions with try and catch statements.
With external processes, we often can make our programs simpler. We can replace threads (which are complex) with external processes (which are isolated). This is maintainable.