1. Overview

In this tutorial, we’ll learn how to invoke external commands from Kotlin. First, we’ll use the ProcessBuilder class. Then, we’ll look at the same using the Runtime class.

2. Using the ProcessBuilder Class

As we know, executing a command from an application is an OS-dependent exercise. If we want to run an application on different systems, we must handle that dependency in code.

Now, we’ll see how to execute a command with the ProcessBuilder class. It provides an easy-to-use but powerful way to execute a command. Moreover, it allows us to manage many attributes of the process we invoke.

Let’s look at a simple example:

@Test
fun `Given a command, When executed with ProcessBuilder, Then it is executed successfully`() {
    val result = ProcessBuilder("java", "-version")
      .redirectOutput(ProcessBuilder.Redirect.INHERIT)
      .redirectError(ProcessBuilder.Redirect.INHERIT)
      .start()
      .waitFor()
    assertThat(result).isEqualTo(0)
}

Here, we execute the java -version command. Additionally, we redirect the standard output and the error output to the parent process. Thanks to that, we can see the output from the execution. After that, we start the process and wait until the execution is finished. As expected, the process finished successfully.

3. Using the Runtime Class

Now, let’s use the Runtime class. Runtime provides an API to interact with the environment in which the application is running.

That’s to say, the Runtime class provides an exec() method, which executes the command we provide:

@Test
fun `Given a command, When executed with Runtime, Then it is executed successfully`() {
    val process = Runtime.getRuntime().exec("java -version")
    val result = process.waitFor()
    assertThat(result).isEqualTo(0)
}

Here, we executed the command in a separate process. The output is not visible in the console, because we don’t redirect the output. While could redirect the output, it’s not as straightforward as in the previous section.

It’s important to note that the exec() method is deprecated starting from JDK 18. It’s error-prone and it’s recommended not to use it. Instead, use the substitute exec() method as follows:

@Test
fun `Given a command, When executed with Runtime, Then it is executed successfully`() {
    val process = Runtime.getRuntime().exec(arrayOf("java", "-version"))
    val result = process.waitFor()
    assertThat(result).isEqualTo(0)
}

4. Conclusion

In this short article, we saw how to execute an external command using the ProcessBuilder and Runtime classes.

As always, the source code of the examples is available over on GitHub.

2 Comments
Oldest
Newest
Inline Feedbacks
View all comments
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.