Java9 进程API详细介绍

官方在JEP 102中引进新的进程API来增强Java.lang.Process 类,并且引进java.lang.ProcessHandle 及其嵌套接口Info 来让开发者逃离时常因为要获取一个本地进程的PID而不得不使用本地代码的窘境。本文将详细介绍这些新特性。

1、ProcessHandle 与 ProcessHandle.Info

Java 9 为抽象Process 类增加了许多新方法,通过这些方法可以识别直接子进程与所有后代进程, 获取进程的PID、 获取进程的快照、获取CompletableFuture 实例来接收进程结束时的异步通知,以及更多特性的获取:

Stream<ProcessHandle> children() Stream<ProcessHandle> descendants() long getPid() ProcessHandle.Info info() CompletableFuture<Process> onExit() boolean supportsNormalTermination() ProcessHandle toHandle()

可以看出,超过半数的方法是需要结合ProcessHandle 接口来使用的, ProcessHandle 接口可以识别并控制本地进程。例如,toHandle() 方法可以返回ProcessHandle 的具体实现对象和与之关联的进程,ProcessHandle 中声明的方法如下:

static Stream<ProcessHandle> allProcesses() Stream<ProcessHandle> children() int compareTo(ProcessHandle other) static ProcessHandle current() Stream<ProcessHandle> descendants() boolean destroy() boolean destroyForcibly() long getPid() ProcessHandle.Info info() boolean isAlive() static Optional<ProcessHandle> of(long pid) CompletableFuture<ProcessHandle> onExit() Optional<ProcessHandle> parent() boolean supportsNormalTermination()

Process 中的方法以方法名通过调用toHandle() 方法委派给ProcessHandle 接口。例如,调用getPid() 是调用 toHandle().getPid(),调用info()是调用 toHandle().info(),返回的是ProcessHandle.Info 对象,其嵌套接口Info 提供以下方法列表:

Optional<String[]> arguments() Optional<String> command() Optional<String> commandLine() Optional<Instant> startInstant() Optional<Duration> totalCpuDuration() Optional<String> user()

每个方法返回java.util.Optional 实例,可能是null或非空对象引用, 大家都知道这样能有效避免java.lang.NullPointerException。您将在下文详细了解这些方法。

2、获取PID

Process 的long getPid() 方法返回特定进程的PID。 之所以返回值是long类型而不是int类型,是因为PID是无符号整型。 最大的正值整型约为200万,但是Linux系统可以容纳大概400万个PID。

下面是获取PID的方式:

import java.io.IOException; public class ProcessDemo { public static void main(String[] args) throws IOException { Process p = new ProcessBuilder("notepad.exe").start(); System.out.println(p.getPid()); } }

java.lang.ProcessBuilder 类(引进于Java 5) 为Windows的notepad.exe程序构建了一个进程。用start() 方法开启,返回了一个Process 对象来与新进程进行交互。 然后再调用getPid() 方法来获取PID。

产生新进程的方式

在Java 5之前,产生新进程的唯一方式是使用Runtime.getRuntime().exec() ,而现在更好的方式是使用ProcessBuilder。

编译ProcessDemo.java:

javac ProcessDemo.java

运行ProcessDemo.java:

java ProcessDemo

你可以在进程管理器看到一个新的进程notepad.exe 正在运行,并且可以看到它的PID。

9480 或者其他无符号整型

从进程句柄获取PID

如果有一个ProcessHandle 对象,可以通过调用getPid() 来获取PID。

你一定很想知道在调用这个方法的时候如果进程无法启动或者已经意外终止会发生什么,第一种情况, start() 抛出 java.io.IOException ,第二种情况, getPid() 继续在进程终止后返回PID。

3、获取进程信息

ProcessHandle.Info 定义了一些返回进程信息的方法,比如,进程的可执行路径名,进程的开启时间,开启进程的用户等等。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/47d750fb3af6f60f18eb68311710a064.html