Process API Improvement

Java has improved its process API in Java 9 version by adding new methods in Process class and new interfaces ProcessHandle and ProcessHandle.Info.

It is helpful in controlling and managing processes whether OS-based or application processes. We can create processes, get information about processes like process id, owner name, waiting time, process status, etc.

Two new interfaces in Process API:

  • java.lang.ProcessHandle
  • java.lang.ProcessHandle.Info

The Process class in Java provides several methods to handle the process and perform operations like check waiting for the process to complete, checking the exit status of the process, and destroying (killing) the process, etc.

The following are some methods that added in Java 9 version to the Process class.

Java Process class Methods (Only Java 9 methods)

Method Description

boolean supportsNormalTermination()

It returns true if the implementation of destroy() is to normally terminate the process, else returns false.

ProcessHandle toHandle()

It returns a ProcessHandle for the Process.

long pid()

It returns the native process ID of the process.

Stream<ProcessHandle> children()

It returns a snapshot of the direct children of the process.

Stream<ProcessHandle> descendants()

It returns a snapshot of the descendants of the process.

ProcessHandle.Info info()

It returns a snapshot of information about the process.

CompletableFuture<Process> onExit()

It returns a CompletableFuture<Process> for the termination of the Process.

Example: Find Process Id

Let's understand the process handling by a simple example. Here, we are getting process id using the pid() method of Process class.

public class Main { 
	public static void main(String[] args){
		ProcessHandle currentProcess = ProcessHandle.current();
        System.out.println("Process Id: "+currentProcess.pid());    
	}
}


Process Id: 16458

Java ProcessHandle Interface

Java added this interface that identifies and provides control of native processes. It can be helpful to get list of its children, information of a process or destroy a process etc. The syntax of the method is given below.

public interface ProcessHandle extends Comparable<ProcessHandle>

Interface Methods

Following are the methods of ProcessHandle Interface. It contains one nested interface called Info.

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 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 other object is non-null, is of the same implementation, and represents the same system process; otherwise it 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.

In our previous example, we fetched the process id of the currently running process. However, we can start a new process by own and handle it.

Example: Start Vi Editor in Linux

Now, let's create a new process by using the start() method of ProcessBuilder class. Here, we are starting a process of vim editor in Linux and getting process id using the pid() method.

public class Main { 
	public static void main(String[] args) throws IOException{
		 Process p = new ProcessBuilder("vim").start();
	      System.out.println(p.pid()); 
	}
}


13834

Example: Process Information

This example explains how can we get information of a process. We used pid(), isAlive(), info(), hashCode(), etc methods of Process class.

import java.io.IOException;

public class Main { 
	public static void main(String[] args) throws IOException{
		 Process p = new ProcessBuilder("vim").start();
		 // Get process ID
	     System.out.println(p.pid());
	     // Check is Alive?
	     System.out.println(p.isAlive());
	     // Get process Info
	     System.out.println(p.info());
	     // Get Hahscode
	     System.out.println(p.hashCode());
	     // Get child process
	     System.out.println(p.children());
	     // Get className
	     System.out.println(p.getClass());
	}
}


14413
true
[user: Optional[root], cmd: /usr/bin/vim.basic, startTime: Optional[2020-07-23T19:02:42.310Z], totalTime: Optional[PT0S]]
1418481495
[email protected]
class java.lang.ProcessImpl

Java ProcessHandle.Info Interface

This interface provides information snapshots about the process. It is a nested interface of ProcessHandle interface. Each operating system's process attributes are not similar and are not available in all implementations. Information about processes is limited by the operating system privileges of the process making the request. The signature of this interface is given below.

public static interface ProcessHandle.Info

ProcessHandle.Info Methods

The following are the methods of ProcessHandle.info interface which is a static and nested interface

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 cputime accumulated of the process.

Optional<String> user()

It returns the user of the process.

Example:

Here, we are using ProcessHandle.Info interface methods to get information about the process.

import java.io.IOException;
import java.time.Duration;

public class Main { 
	public static void main(String[] args) throws IOException{
		ProcessHandle.Info info = ProcessHandle.current().info();
		System.out.println(info.arguments());
		System.out.println(info.command().orElse("Not Found"));
		String[] argz = info.arguments().orElse(new String[] {});
		for (String arg: argz)
	         System.out.printf("   %s%n", arg);
		System.out.println("Owner: "+info.user());
		System.out.println("RunTime: "+info.totalCpuDuration().orElse(Duration.ofMillis(0)).toMillis());
		
	}
}


Optional[[Ljava.lang.String;@1f32e575]
/usr/lib/jvm/java-11-openjdk-amd64/bin/java
-Dfile.encoding=UTF-8
-classpath
/home/root/eclipse/myjavaproject/bin:/home/root/Downloads/mongo-java-driver-3.12.4.jar:/home/root/Downloads/opencsv-3.8.jar:/home/root/Downloads/commons-logging-1.2/commons-logging-1.2.jar:/home/root/Downloads/pdfbox-2.0.12.jar:/home/root/Downloads/fontbox-2.0.12.jar
myjavaproject.Main
Owner: Optional[root]
RunTime: 100