With the introduction of Java 9, various improvements have been made in the Process API. Process API in Java 9 version helps to manage and control operating system processes. In Java 8 and earlier versions, the API lacks some key functionality, which makes handling processes in Java a mess. The limitations of the API often force developers to resort to native code in earlier Java versions. Now, new classes and interfaces are added to perform this task.
As we know, the Process API provides control of native processes. The class provides methods for performing input from the process, performing output to the process, waiting for the process to complete, checking the exit status of the process, and destroying (killing) the process.
What are the new features of the ProcessAPI in Java 9?
The Process API lacks some key functionality, so developers have to write a messy code to perform those tasks. For example, in order to do something as simple as getting your process PID in earlier versions of Java, you would need to either access native code or use some sort of a workaround. The process of doing so is very cumbersome.
Java 9 comes to fix those issues and provide a clean API for interaction with processes. It enhances the Process class and introduces ProcessHandle with its nested interface Info to overcome the limitations we had in the past. More specifically two new interfaces have been added to the JDK:
1. java.lang.ProcessHandle
2. java.lang.ProcessHandle.Info
ProcessHandle:
ProcessHandle identifies and provides control of native processes. Each individual process can be monitored for liveness, list its children, get information about the process or destroy it. By comparison, Process instances were started by the current process and additionally provide access to the process input, output, and error streams.
Modifier and Type | Method | Description |
---|---|---|
static Stream<ProcessHandle> | allProcesses() | It returns a snapshot of all processes visible to the current process. |
Stream<ProcessHandle> | children() | It returns a snapshot of the current direct children of the process. |
int | compareTo(ProcessHandle other) | It compares this ProcessHandle with the specified ProcessHandle for the order. |
static ProcessHandle | current() | It returns a ProcessHandle for the current process. |
Stream<ProcessHandle> | descendants() | It returns a snapshot of the descendants of the process. |
boolean | destroy() | It requests the process to be killed. |
boolean | destroyForcibly() | It requests the process to be killed forcibly. |
boolean | equals(Object other) | It returns true if another object is non-null, is of the same implementation, and represents the same system process; otherwise, it returns false. |
int | hashCode() | It returns a hash code value for this ProcessHandle. |
ProcessHandle.Info | info() | It returns a snapshot of information about the process. |
boolean | isAlive() | It tests whether the process represented by this ProcessHandle is alive. |
static Optional<ProcessHandle> | of(long pid) | It returns an Optional<ProcessHandle> for an existing native process. |
CompletableFuture<ProcessHandle> | onExit() | It returns a CompletableFuture<ProcessHandle> for the termination of the process. |
Optional<ProcessHandle> | parent() | It returns an Optional<ProcessHandle> for the parent process. |
long | pid() | It returns the native process ID of the process. |
boolean | supportsNormalTermination() | It returns true if the implementation of destroy() normally terminates the process. |
ProcessHandle.Info:
ProcessHandle.Info gives information snapshot about the process. The attributes of a process vary by the operating system and are not available in all implementations. Information about processes is limited by the operating system privileges of the process making the request. The return types are Optional<T> allowing explicit tests and actions if the value is available.
Modifier and Type | Method | Description |
---|---|---|
Optional<String[]> | arguments() | It returns an array of Strings of the arguments of the process. |
Optional<String> | command() | It returns the executable pathname of the process. |
Optional<String> | commandLine() | It returns the command line of the process. |
Optional<Instant> | startInstant() | It returns the start time of the process. |
Optional<Duration> | totalCpuDuration() | It returns the total CPU time accumulated of the process. |
Optional<String> | user() | It returns the user of the process. |
Let’s look at a few examples to understand the above two interfaces in a better way.
public class ProcessApiDemo { public static void main(String[] args) { ProcessHandle currentProcessHandleImpl = ProcessHandle.current(); System.out.println("Native process ID of the process: " + currentProcessHandleImpl.pid()); //Get process Id of current native process System.out.println("\nDirect children: " + currentProcessHandleImpl.children()); // Direct children of the process System.out.println("\nClass name: " + currentProcessHandleImpl.getClass()); // Class name System.out.println("\nAll processes: " + ProcessHandle.allProcesses()); // All current processes System.out.println("\nProcess info: " + currentProcessHandleImpl.info()); // Process info System.out.println("\nIs process alive: " + currentProcessHandleImpl.isAlive()); System.out.println("\nProcess's parent " + currentProcessHandleImpl.parent()); // Parent of the process //Process snapshot of the current running process with ProcessHandle.Info: ProcessHandle.Info processInfo = currentProcessHandleImpl.info(); System.out.println("\nProcess snapshot of the current running process:"); System.out.println("User : " + processInfo.user().get()); System.out.println("Start Time : " + processInfo.startInstant().get()); } }
In the above example, we have seen various methods associated wit ProcessHandle and ProcessHandle.Info that can be leveraged in our code to work with the system’s processes in a better way.
Conclusion:
ProcessHandle identifies and provides control of native processes. Each individual process can be monitored for liveness, list its children, get information about the process or destroy it.
Using the java.lang.ProcessHandle.Info API, we can now obtain a lot of information about the process like:
- the command used to start the process
- the arguments of the command
- time instant when the process was started
- total time spent by it and the user who created it
I hope, you have liked my blog. If you have any doubts or suggestions to make please drop a comment. Thanks!
References:
Process API official doc