Java9在改进进程管理API方面,主要的更新在于引入了ProcessHandle接口,该接口代表了一个本地进程,并提供了许多与进程相关的信息和操作。
通过ProcessHandle接口,开发者可以获取进程的ID、父进程、子进程、进程命令行参数、进程状态等信息。
具体来说,ProcessHandle接口提供了一系列方法来获取进程的信息,例如pid()用于获取进程ID,info()用于获取进程的详细信息,parent()用于获取父进程的ProcessHandle,children()用于获取子进程的ProcessHandle数组等。
此外,ProcessHandle接口还支持对进程的监控。开发者可以使用onExit()方法注册一个回调,当进程退出时,系统会自动调用该回调,从而允许在进程退出时执行一些特定的操作。
总的来说,Java9在进程管理API方面的改进,使得开发者能够更方便地获取进程信息,并对进程进行更细致的管理和监控。
ProcessHandle类的介绍
该类在java.lang
包中,且处于java.base
模块中。
ProcessHandle可以用于获取进程信息,监听和检查进程的状态,并且可以监听进程的退出。
主要提供了以下几个方法:
- allProcesses():返回当前进程可见的所有进程的快照
- current():返回当前进程的ProcessHandle实例
- of(long pid):返回现有本机进程的Optional
- children():返回进程的当前直接子进程的快照
- compareTo(ProcessHandle other):比较两个进程
- descendants():返回当前进程后代的快照
- destroy():请求杀死当前进程
- destroyForcibly():强制杀死该进程
- info():返回有关该进程的信息的快照
- isAlive():测试此ProcessHandle表示的进程是否处于活动状态
- onExit():当进程终止时返回CompletableFuture
- parent():返回当前进程的父进程Optional,因为当前进程可能是初始进程,所以父进程不一定存在
- pid():返回当前进程的系统进程的id
- supportsNormalTermination():如果destroy()正常终止进程,则返回true
ProcessHandle类用于标识并提供对native进程的控制,可以监控每个单独的进程的活跃度,列出其子进程(线程),获取有关进程的信息或将其销毁。
而很早就存在的Process类,它的实例由当前进程启动,只提供了对进程输入,输出和错误流的访问。
native进程ID是操作系统分配给进程的标识号,这个ID值的范围取决于操作系统,例如,嵌入式系统可能使用16位值。
关于这个ProcessHandle类,还有很多信息,如果你对此感兴趣,可以访问官方API文档:Interface ProcessHandle
ProcessHandle类的使用
package com.morris.java9;
import java.io.IOException;
import java.util.stream.Stream;
/**
* ProcessHandle类的使用
*/
public class ProcessHandleDemo {
public static void main(String[] args) throws IOException, InterruptedException {
// 获取当前进程的 ProcessHandle
ProcessHandle currentProcess = ProcessHandle.current();
long pid = currentProcess.pid();
System.out.println("Current Process ID: " + pid);
// 获取进程启动时的命令行参数
System.out.println("Command line arguments: " + currentProcess.info().arguments());
// 遍历所有进程
Stream<ProcessHandle> allProcesses = ProcessHandle.allProcesses();
allProcesses.forEach(process -> {
System.out.println("Process ID: " + process.pid());
System.out.println("Command: " + process.info().command().orElse("Unknown"));
});
// 启动一个子进程
ProcessBuilder processBuilder = new ProcessBuilder("ping", "www.baidu.com");
Process process = processBuilder.start();
// 监听进程退出
// onExit for current process not allowed
process.toHandle().onExit().thenAccept(exitValue -> System.out.println("Process exited with code: " + exitValue));
// 获取进程的子进程
Stream<ProcessHandle> children = currentProcess.children();
children.forEach(child -> System.out.println("Child Process ID: " + child.pid()));
// 在命令行kill上面的子进程
Thread.sleep(100 * 1000);
}
}
运行结果如下:
$ java com.morris.java9.ProcessHandleDemo
Current Process ID: 755
Command line arguments: Optional[[Ljava.lang.String;@6fb554cc]
Process ID: 1
Command: /usr/lib/systemd/systemd
Process ID: 2
Command: /usr/bin/su
Process ID: 3
Command: /usr/bin/bash
Process ID: 60
Command: /usr/lib/systemd/systemd-journald
Process ID: 89
Command: /usr/lib/systemd/systemd-udevd
Process ID: 94
Command: /usr/lib/systemd/systemd-networkd
Process ID: 249
Command: /usr/lib/systemd/systemd-resolved
Process ID: 252
Command: /usr/lib/accountsservice/accounts-daemon
Process ID: 253
Command: /usr/bin/dbus-daemon
Process ID: 256
Command: /usr/bin/python3.8
Process ID: 258
Command: /usr/lib/policykit-1/polkitd
Process ID: 260
Command: /usr/sbin/rsyslogd
Process ID: 261
Command: /usr/lib/systemd/systemd-logind
Process ID: 263
Command: /usr/lib/udisks2/udisksd
Process ID: 289
Command: /usr/sbin/cron
Process ID: 293
Command: /usr/bin/python3.8
Process ID: 294
Command: /usr/bin/containerd
Process ID: 295
Command: /usr/sbin/atd
Process ID: 303
Command: /usr/sbin/ModemManager
Process ID: 311
Command: /usr/sbin/agetty
Process ID: 315
Command: /usr/sbin/agetty
Process ID: 318
Command: /usr/sbin/sshd
Process ID: 339
Command: /usr/bin/dockerd
Process ID: 362
Command: /usr/bin/containerd-shim-runc-v2
Process ID: 383
Command: /docker-volume-sshfs
Process ID: 687
Command: /usr/bin/su
Process ID: 689
Command: /usr/lib/systemd/systemd
Process ID: 690
Command: /usr/lib/systemd/systemd
Process ID: 695
Command: /usr/bin/bash
Process ID: 755
Command: /root/soft/jdk-9.0.4/bin/java
Child Process ID: 789
Process exited with code: 789
在操作系统层面也能看到这个进程:
$ ps -ef|grep 716
root 716 3 0 14:34 pts/0 00:00:00 java com.morris.java9.ProcessHandleDemo
root 754 695 0 14:36 pts/1 00:00:00 grep --color=auto 716
$ ps -ef|grep 755
root 755 3 1 14:36 pts/0 00:00:00 java com.morris.java9.ProcessHandleDemo
root 789 755 0 14:36 pts/0 00:00:00 ping www.baidu.com
root 792 695 0 14:36 pts/1 00:00:00 grep --color=auto 755
$ kill 789