39

Is there a way to start a process in Java? in .Net this is done with for example:

System.Diagnostics.Process.Start("processname");

Is there an equivalent in Java so I can then let the user find the application and then it would work for any OS?

Chris
  • 1,416
  • 18
  • 29
jmasterx
  • 52,639
  • 96
  • 311
  • 557

3 Answers3

37

http://www.rgagnon.com/javadetails/java-0014.html

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.file.Paths;

public class CmdExec {

public static void main(String args[]) {
    try {
        // enter code here

        Process p = Runtime.getRuntime().exec(
            Paths.get(System.getenv("windir"), "system32", "tree.com /A").toString()
        );

        // enter code here

        try(BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
            String line;

            while ((line = input.readLine()) != null) {
                System.out.println(line);
            }
        }

    } catch (Exception err) {
        err.printStackTrace();
    }
  }
}

You can get the local path using System properties or a similar approach.

http://download.oracle.com/javase/tutorial/essential/environment/sysprop.html

Eugene Lebedev
  • 1,400
  • 1
  • 18
  • 30
James P.
  • 19,313
  • 27
  • 97
  • 155
  • 10
    Note that you should use the `.exec(String[])` form of the method, not the single string `.exec(String)` form which *is not a command line processor* -- it simply splits on spaces. They give the same result for this example `tree.com /A` but are different if given, for example, a filename that has spaces in it. – Stephen P Sep 23 '10 at 01:05
  • 2
    You should also flush the error stream and if necessary wait for the process output value. – Giovanni Botta Jul 17 '13 at 19:23
  • your code contains possible resource leak. i recommend to use try-resource language feature. – Eugene Lebedev Oct 03 '18 at 09:23
  • 1
    @EvgenyLebedev can you edit the answer above to reflect that? – James P. Oct 04 '18 at 20:51
  • @GiovanniBotta can you edit the answer with added comments? – James P. Oct 04 '18 at 20:51
  • 1
    @james-p your answer has been improved :) – Eugene Lebedev Oct 11 '18 at 12:41
  • As of Java 1.5, ProcessBuilder.start() is the preferred way to create a Process [javadoc](https://docs.oracle.com/javase/8/docs/api/java/lang/Process.html) – zer_ik Sep 01 '22 at 15:43
  • Unfortunately this code won't work properly for all commands as stderr is not consumed at same time as stdout - it will freeze if there is a lot of output to stderr. You can demonstrate with command set to `new String[] {"cmd.exe", "/c", "FOR /L %X IN (1, 1, 10000) DO echo Hello STDOUT %X && echo Hello STDERR 1>&2" }` or `new String[] {"/bin/bash", "-c", "for i in {1..30000} ; do echo Hello STDERR $i 1>&2 ; done ; echo Hello STDOUT" }` – DuncG Oct 02 '22 at 15:15
28

The Java Class Library represents external processes using the java.lang.Process class. Processes can be spawned using a java.lang.ProcessBuilder:

Process process = new ProcessBuilder("processname").start();

or the older interface exposed by the overloaded exec methods on the java.lang.Runtime class:

Process process = Runtime.getRuntime().exec("processname");

Both of these will code snippets will spawn a new process, which usually executes asynchronously and can be interacted with through the resulting Process object. If you need to check that the process has finished (or wait for it to finish), don't forget to check that the exit value (exit code) returned by process.exitValue() or process.waitFor() is as expected (0 for most programs), since no exception is thrown if the process exits abnormally.

Also note that additional code is often necessary to handle the process's I/O correctly, as described in the documentation for the Process class (emphasis added):

By default, the created subprocess does not have its own terminal or console. All its standard I/O (i.e. stdin, stdout, stderr) operations will be redirected to the parent process, where they can be accessed via the streams obtained using the methods getOutputStream(), getInputStream(), and getErrorStream(). The parent process uses these streams to feed input to and get output from the subprocess. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, or even deadlock.

One way to make sure that I/O is correctly handled and that the exit value indicates success is to use a library like jproc that deals with the intricacies of capturing stdout and stderr, and offers a simple synchronous interface to run external processes:

ProcResult result = new ProcBuilder("processname").run();

jproc is available via maven central:

<dependency>
      <groupId>org.buildobjects</groupId>
      <artifactId>jproc</artifactId>
      <version>2.5.1</version>
</dependency>
Felix Leipold
  • 1,064
  • 10
  • 17
24

See Runtime.exec() and the Process class. In its simplest form:

Process myProcess = Runtime.getRuntime().exec(command);
...

Note that you also need to read the process' output (eg: myProcess.getInputStream()) -- or the process will hang on some systems. This can be highly confusing the first time, and should be included in any introduction to these APIs. See James P.'s response for an example.

You might also want to look into the new ProcessBuilder class, which makes it easier to change environment variables and to invoke subprocesses :

Process myProcess = new ProcessBuilder(command, arg).start();
...
NullUserException
  • 83,810
  • 28
  • 209
  • 234
  • You also need to read the process's output -- p.getInputStream() -- or the process will hang on some systems. This can be highly confusing the first time, and should be included in any introduction to these APIs. See James P.'s response for an example. – Andy Thomas Sep 23 '10 at 00:08
  • @Andy Thanks. I incorporated your comment into my answer if you don't mind. – NullUserException Sep 23 '10 at 00:15
  • what if the default media player is VLC and I want to for example open "somevideo.avi" and I want it to use the default application which is vlc? – jmasterx Sep 23 '10 at 00:19