Java 简明教程

Java - Process API Improvements

在 Java 9 中,负责控制和管理操作系统进程的 Process API 已得到极大改进。ProcessHandle 类现在提供进程的本机进程 ID、启动时间、累积的 CPU 时间、参数、命令、用户、父进程和后代。ProcessHandle 类还提供用于检查进程的活跃状态和销毁进程的方法。它有 onExit 方法,CompletableFuture 类可以在进程退出时异步执行动作。

In Java 9 Process API which is responsible to control and manage operating system processes has been improved considerably. ProcessHandle Class now provides process’s native process ID, start time, accumulated CPU time, arguments, command, user, parent process, and descendants. ProcessHandle class also provides method to check processes' liveness and to destroy processes. It has onExit method, the CompletableFuture class can perform action asynchronously when process exits.

Spawning a new Process Example

在此示例中,我们为记事本创建了一个新的 Process,并使用 ProcessBuilder 启动了该 Process。使用 ProcessHandle.Info 接口,我们正在获取新生成的进程的进程信息。

In this example, we’ve created a new Process for notepad and started it using ProcessBuilder. Using ProcessHandle.Info interface, we’re getting the process information of the newly spawned process.

package com.tutorialspoint;

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

你将看到类似的输出。

You will see the similar 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\Tutorialspoint

Getting Current Process Information Example

在此示例中,我们使用 ProcessHandle.current() 方法获取了当前进程。然后使用 ProcessHandle.Info 接口,我们正在获取当前进程的进程信息。

In this example, we’ve getting current process using ProcessHandle.current() method. Then using ProcessHandle.Info interface, we’re getting the process information of the current process.

package com.tutorialspoint;

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

你将看到类似的输出。

You will see the similar 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\Tutorialspoint

Getting Child Processes Example

在此示例中,我们使用 ProcessHandle.current().children() 方法获取当前进程的子进程。然后使用 ProcessHandle.Info 接口获取子进程的进程信息。

In this example, we’ve getting current process chid processes using ProcessHandle.current().children() method. Then using ProcessHandle.Info interface, we’re getting the process information of the child processes.

package com.tutorialspoint;

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<ProcessHandle> 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

你将看到类似的输出。

You will see the similar 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)
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)
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)