Process API enhancements in Java 9

The java.lang.Process class provides methods to get input or output from a process, wait for process to complete, check exit status or kill the process. From Java 7 onwards, the process streams could be redirected to files.

In Java 9, certain enhancements(JEP 102) were done to the Process API and a new interface called ProcessHandle was also introduced. The newly added methods of java.lang.Process class are:

  • Stream<ProcessHandle> children()
    Returns a snapshot of direct children for the given process.
  • Stream<ProcessHandle> descendants()
    Gives a snapshot of all the children in the process tree including direct children and their descendents.
  • long pid()
    Gives native process ID of the process.
  • ProcessHandle.Info info()
    The ProcessHandle.Info returned by this method has methods that gives more information about the process.
  • CompletableFuture<Process> onExit()
    The CompletableFuture returned allows to trigger important functions/actions that may be required while exiting the process.
  • boolean supportsNormalTermination()
    The method destroy() is used to kill a given process. The method supportsNormalTermination() returns true if implementation of destroy() is to terminate the process normally and false if it forcibly terminates the process immediately if invoked.
  • ProcessHandle toHandle()
    Returns a ProcessHandle for the process.

Let us learn more about the new changes with some examples

Creating A New Process And Getting Its ID

The methods ProcessHandle.pid() returns a long value that denotes the process id of the invoking process. Since native OS level processes have unsigned integer values for process IDs, the return value for this method is kept as long.

Consider the following example:

Running the above program will give the following output:

Obtaining Process Information

To get more details about a given process, we can get an instance of ProcessHandle.Info by invoking Process.info() on the process object. The ProcessHandle.Info returned by the method contains access methods to get more information about the given process. An instance of ProcessHandle for a given process can be obtained using Process.toHandle().

Each method that is available in the ProcessHandle.Info returns an instance of java.util.Optional. The Optional class is just a container object that may or may not contain values. To make sure that our sample programs works seamlessly, we have added the .orElse() construct wherever necessary in subsequent sections. The methods like orElse(), orElseGet() and orElseThrow() are used to suggest what has to be done in case the Optional instance does not have any value associated with it.

The following code illustrates how the ProcessHandle.Info can be used to obtain information about a given process programmatically:

 

In the above program, information about the current process (java process)  is obtained in main() method using ProcessHandle.current(). Process.toHandle() gives a process handle for the newly created process for notepad.exe. Both these handles are passed to printInfo() method to get the respective process information.

Output for the above code will be as follows:

Obtaining Process Information On Termination

It is possible to get the state of a process right after it is terminated. While creating a process, we can invoke process.waitFor(). The waitFor() method is similar to the normal wait() used in multi-threaded applications in synchronized context. It directs the current process to wait till the invoked process is terminated.

Consider the following example:

In the above program, the first printInfo() executes right after launching the paint process. The second printInfo() statement does not execute till we close the paint window.

Output for the above program will be as follows:

Note that while printing the process information for second time, the original executable path obtained from ProcessHandle.Info.command() earlier is not printed. Instead, the string “No path” is printed. This is because we had used the .orElse() construct to print “No path” if the Optional object returned by command() function does not have any value associated with it. The  printInfo() method is invoked again for a second time by current process only after it is notified that the process created programmatically is terminated. Note that the “Total Up Time” value printed during termination of the process is larger than the one printed by process handle while starting the mspaint application.

Obtaining Process Information Of Children

It is possible to get a list of children for the current process and print information for them programmatically. The sample code below demonstrates how this can be achieved by using lambdas and streams.

Consider the following example:

In the above code, the current process creates a new process for notepad, paint and window explorer applications. Hence those new processes become children of the current java process.

Output of the above program will be as follows:

ProcessHandle.children() returns a Stream containing handles these three processes. Data of each process is printed by invoking printInfo() for each handle using lambda expression:

To print the information on all processes that are visible to the current process, we can alter the above lambda expression to the following:

Note the filter applied in above statement. Optional.isPresent() returns true if value is present in the given object. Thus, the filter makes sure that information is printed only if the process is running and not terminated. In the section “Obtaining Process Information On Termination” we saw how a ProcessHandle.Info.command() does not contain value once a given process is terminated. So, this is a better approach to make sure that only data of active processes are printed to the console.

 

Summary

Process API has been improved in Java 9 for controlling and managing operating-system process. With Java 9 it is possible to get information about any spawned process including the current process. And hence these changes are definitely going to make it easier to work with Process API.

3 thoughts to “Process API enhancements in Java 9”

  1. The best part I like is getting the PID of a process, it is really pain in java8. Is it going to be backported to java 8?

Leave a Reply