Java Process API Improvements in Java 9: Managing OS Processes with Enhanced Features
Explore the significant improvements made to the Process API in Java 9. The ProcessHandle
class now provides detailed process information, such as process ID, CPU time, arguments, and more. Learn how the new onExit
method enables asynchronous actions when a process exits, and discover how to spawn new processes using the ProcessBuilder
class.
Java - Process API Improvements
In Java 9, the Process API, responsible for controlling and managing operating system processes, underwent significant improvements. The ProcessHandle
class now provides details such as the process's native process ID, start time, accumulated CPU time, arguments, command, user, parent process, and descendants. The ProcessHandle
class also includes methods to check process liveness and to destroy processes. Additionally, it features an onExit
method that uses CompletableFuture
to perform actions asynchronously when a process exits.
Spawning a New Process Example
In this example, we create a new process for Notepad and start it using ProcessBuilder
. We retrieve the process information of the newly spawned process using the ProcessHandle.Info
interface.
Example
package com.tutorialsarena;
import java.time.ZoneId;
import java.util.stream.Stream;
import java.util.stream.Collectors;
import java.io.IOException;
public class Tester {
public static void main(String[] args) throws IOException {
ProcessBuilder pb = new ProcessBuilder("notepad.exe");
String np = "Not Present";
Process p = pb.start();
ProcessHandle.Info info = p.info();
System.out.printf("Process ID : %s%n", p.pid());
System.out.printf("Command name : %s%n", info.command().orElse(np));
System.out.printf("Command line : %s%n", info.commandLine().orElse(np));
System.out.printf("Start time: %s%n",
info.startInstant().map(i -> i.atZone(ZoneId.systemDefault())
.toLocalDateTime().toString()).orElse(np));
System.out.printf("Arguments : %s%n",
info.arguments().map(a -> Stream.of(a).collect(
Collectors.joining(" "))).orElse(np));
System.out.printf("User : %s%n", info.user().orElse(np));
}
}
Output
Process ID : 5580
Command name : C:\Program Files\WindowsApps\Microsoft.WindowsNotepad_11.2401.26.0_x64__8wekyb3d8bbwe\Notepad\Notepad.exe
Command line : Not Present
Start time: 2024-04-02T17:07:14.305
Arguments : Not Present
User : DESKTOP\tutorialsarena
Getting Current Process Information Example
In this example, we retrieve information about the current process using the ProcessHandle.current()
method. The ProcessHandle.Info
interface is used to get the process information of the current process.
Example
package com.tutorialsarena;
import java.time.ZoneId;
import java.util.stream.Stream;
import java.util.stream.Collectors;
import java.io.IOException;
public class Tester {
public static void main(String[] args) throws IOException {
String np = "Not Present";
ProcessHandle currentProcess = ProcessHandle.current();
ProcessHandle.Info info = currentProcess.info();
System.out.printf("Process ID : %s%n", currentProcess.pid());
System.out.printf("Command name : %s%n", info.command().orElse(np));
System.out.printf("Command line : %s%n", info.commandLine().orElse(np));
System.out.printf("Start time: %s%n",
info.startInstant().map(i -> i.atZone(ZoneId.systemDefault())
.toLocalDateTime().toString()).orElse(np));
System.out.printf("Arguments : %s%n",
info.arguments().map(a -> Stream.of(a).collect(
Collectors.joining(" "))).orElse(np));
System.out.printf("User : %s%n", info.user().orElse(np));
}
}
Output
Process ID : 5352
Command name : C:\Program Files\Java\jdk-21\bin\javaw.exe
Command line : Not Present
Start time: 2024-04-02T17:09:17.902
Arguments : Not Present
User : DESKTOP-DTHL8BI\tutorialsarena
Getting Child Processes Example
In this example, we obtain the current process's child processes using the ProcessHandle.current().children()
method. We retrieve the process information of the child processes using the ProcessHandle.Info
interface.
Example
package com.tutorialsarena;
import java.io.IOException;
import java.util.stream.Stream;
public class Tester {
public static void main(String[] args) throws IOException {
for (int i = 0; i < 3; i++) {
ProcessBuilder processBuilder
= new ProcessBuilder("java.exe", "-version");
processBuilder.inheritIO().start();
}
Stream childProcesses = ProcessHandle.current().children();
String np = "Not Present";
childProcesses.filter(ProcessHandle::isAlive).forEach(
childProcess ->{
System.out.printf("Process ID : %s%n", childProcess.pid());
System.out.printf("Command name : %s%n", childProcess.info().command().orElse(np));
System.out.printf("Command line : %s%n", childProcess.info().commandLine().orElse(np));
}
);
}
}
Output
Process ID : 5420
Command name : C:\Program Files\Java\jdk-21\bin\java.exe
Command line : Not Present
Process ID : 15796
Command name : C:\Program Files\Java\jdk-21\bin\java.exe
Command line : Not Present
Process ID : 14180
Command name : C:\Program Files\Java\jdk-21\bin\java.exe
Command line : Not Present
java version "21.0.2" 2024-01-16 LTS
Java(TM) SE Runtime Environment (build 21.0.2+13-LTS-58)
Java HotSpot(TM) 64-Bit Server VM (build 21.0.2+13-LTS-58, mixed mode, sharing)