Java 9 Process API Improvements – Java 9流程API的改进

最后修改: 2017年 3月 1日


1. Overview


The process API in Java had been quite primitive prior to Java 5, the only way to spawn a new process was to use the Runtime.getRuntime().exec() API. Then in Java 5, ProcessBuilder API was introduced which supported a cleaner way of spawning new processes.

在Java 5之前,Java中的进程API是相当原始的,生成一个新进程的唯一方法是使用Runtime.getRuntime().exec() API。然后在Java 5中,ProcessBuilder API被引入,它支持以更简洁的方式生成新进程。

Java 9 is adding a new way of getting information about current and any spawned processes.

Java 9增加了一种新的方式来获取关于当前和任何产生的进程的信息。

In this article, we will look at both of these enhancements.


2. Current Java Process Information


We can now obtain a lot of information about the process via the API java.lang.ProcessHandle.Info API:

现在我们可以通过API java.lang.ProcessHandle.Info API获得很多关于进程的信息。

  • 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

Here’s how we can do that:


private static void infoOfCurrentProcess() {
    ProcessHandle processHandle = ProcessHandle.current();
    ProcessHandle.Info processInfo =;"PID: " +;"Arguments: " + processInfo.arguments());"Command: " + processInfo.command());"Instant: " + processInfo.startInstant());"Total CPU duration: " + processInfo.totalCpuDuration());"User: " + processInfo.user());

It is important to note that java.lang.ProcessHandle.Info is a public interface defined within another interface java.lang.ProcessHandle. The JDK provider (Oracle JDK, Open JDK, Zulu, or others) should provide implementations to these interfaces in such a way that these implementations return the relevant information for the processes.

需要注意的是,java.lang.ProcessHandle.Info是定义在另一个接口java.lang.ProcessHandle中的一个公共接口。JDK 提供者(Oracle JDK、Open JDK、Zulu 或其他)应该为这些接口提供实现,使这些实现能够返回进程的相关信息。

The output depends on the operating system and Java version. Here’s an example of what the output can look like:


16:31:24.784 [main] INFO  c.b.j.process.ProcessAPIEnhancements - PID: 22640
16:31:24.790 [main] INFO  c.b.j.process.ProcessAPIEnhancements - Arguments: Optional[[Ljava.lang.String;@2a17b7b6]
16:31:24.791 [main] INFO  c.b.j.process.ProcessAPIEnhancements - Command: Optional[/Library/Java/JavaVirtualMachines/jdk-13.0.1.jdk/Contents/Home/bin/java]
16:31:24.795 [main] INFO  c.b.j.process.ProcessAPIEnhancements - Instant: Optional[2021-08-31T14:31:23.870Z]
16:31:24.795 [main] INFO  c.b.j.process.ProcessAPIEnhancements - Total CPU duration: Optional[PT0.818115S]
16:31:24.796 [main] INFO  c.b.j.process.ProcessAPIEnhancements - User: Optional[username]

3. Spawned Process Information


It is also possible to get the process information of a newly spawned process. In this case, after we spawn the process and get an instance of the java.lang.Process, we invoke the toHandle() method on it to get an instance of java.lang.ProcessHandle.


The rest of the details remain the same as in the section above:


String javaCmd = ProcessUtils.getJavaCmd().getAbsolutePath();
ProcessBuilder processBuilder = new ProcessBuilder(javaCmd, "-version");
Process process = processBuilder.inheritIO().start();
ProcessHandle processHandle = process.toHandle();

4. Enumerating Live Processes in the System


We can list all the processes currently in the system, which are visible to the current process. The returned list is a snapshot at the time when the API was invoked, so it’s possible that some processes terminated after taking the snapshot or some new processes were added.


In order to do that, we can use the static method allProcesses() available in the java.lang.ProcessHandle interface which returns us a Stream of ProcessHandle:


private static void infoOfLiveProcesses() {
    Stream<ProcessHandle> liveProcesses = ProcessHandle.allProcesses();
        .forEach(ph -> {
  "PID: " +;
  "Instance: " +;
  "User: " +;

5. Enumerating Child Processes


There are two variants to do this:


  • get direct children of the current process
  • get all the descendants of the current process

The former is achieved by using the method children() and the latter is achieved by using the method descendants():


private static void infoOfChildProcess() throws IOException {
    int childProcessCount = 5;
    for (int i = 0; i < childProcessCount; i++) {
        String javaCmd = ProcessUtils.getJavaCmd()
        ProcessBuilder processBuilder
          = new ProcessBuilder(javaCmd, "-version");

    Stream<ProcessHandle> children = ProcessHandle.current()
      .forEach(ph ->"PID: {}, Cmd: {}",,
    Stream<ProcessHandle> descendants = ProcessHandle.current()
      .forEach(ph ->"PID: {}, Cmd: {}",,

6. Triggering Dependent Actions on Process Termination


We might want to run something on termination of the process. This can be achieved by using the onExit() method in the java.lang.ProcessHandle interface. The method returns us a CompletableFuture which provides the ability to trigger dependent operations when the CompletableFuture is completed.


Here, the CompletableFuture indicates the process has completed, but it doesn’t matter if the process has completed successfully or not. We invoke the get() method on the CompletableFuture, to wait for its completion:


private static void infoOfExitCallback() throws IOException, InterruptedException, ExecutionException {
    String javaCmd = ProcessUtils.getJavaCmd()
    ProcessBuilder processBuilder
      = new ProcessBuilder(javaCmd, "-version");
    Process process = processBuilder.inheritIO()
    ProcessHandle processHandle = process.toHandle();"PID: {} has started",;
    CompletableFuture onProcessExit = processHandle.onExit();
    onProcessExit.get();"Alive: " + processHandle.isAlive());
    onProcessExit.thenAccept(ph -> {"PID: {} has stopped",;

The onExit() method is available in the java.lang.Process interface as well.


7. Conclusion


In this tutorial, we covered interesting additions to the Process API in Java 9 that give us much more control over the running and spawned processes.

在本教程中,我们介绍了Java 9中对Process API的有趣补充,这些补充使我们对运行和生成的进程有了更多的控制。

The code used in this article can be found over on GitHub.