加入收藏 | 设为首页 | 会员中心 | 我要投稿 宿州站长网 (https://www.0557zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

Java9 进程API详细详解

发布时间:2021-12-07 16:03:32 所属栏目:教程 来源:互联网
导读:官方在JEP 102中引进新的进程API来增强Java.lang.Process 类,并且引进java.lang.ProcessHandle 及其嵌套接口Info 来让开发者逃离时常因为要获取一个本地进程的PID而不得不使用本地代码的窘境。本文将详细介绍这些新特性。 1、ProcessHandle 与 ProcessHandl

官方在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 定义了一些返回进程信息的方法,比如,进程的可执行路径名,进程的开启时间,开启进程的用户等等。
 
以下代码开启了一个进程,并将此进程的一些信息输出:
 
import java.io.IOException;
 
import java.time.Duration;
import java.time.Instant;
 
public class ProcessDemo
{
   public static void main(String[] args)
      throws InterruptedException, IOException
   {
      dumpProcessInfo(ProcessHandle.current());
      Process p = new ProcessBuilder("notepad.exe", "C:tempnames.txt").start();
      dumpProcessInfo(p.toHandle());
      p.waitFor();
      dumpProcessInfo(p.toHandle());
   }
 
   static void dumpProcessInfo(ProcessHandle ph)
   {
      System.out.println("PROCESS INFORMATION");
      System.out.println("===================");
      System.out.printf("Process id: %d%n", ph.getPid());
      ProcessHandle.Info info = ph.info();
      System.out.printf("Command: %s%n", info.command().orElse(""));
      String[] args = info.arguments().orElse(new String[]{});
      System.out.println("Arguments:");
      for (String arg: args)
         System.out.printf("   %s%n", arg);
      System.out.printf("Command line: %s%n", info.commandLine().orElse(""));
      System.out.printf("Start time: %s%n",
                        info.startInstant().orElse(Instant.now()).toString());
      System.out.printf("Run time duration: %sms%n",
                        info.totalCpuDuration()
                            .orElse(Duration.ofMillis(0)).toMillis());
      System.out.printf("Owner: %s%n", info.user().orElse(""));
      System.out.println();
   }
}
在main() 方法里面首先调用 ProcessHandle.current() 来获取当前进程的句柄,然后用dumpProcessInfo() 方法来输出dump进程的详细信息。接下来启动notepad.exe ,并且dump其进程信息。等到notepad.exe 终止之后,再一次dump了它的信息。
 
dumpProcessInfo() 方法首先输出头标识信息,随后输出PID,随后获取ProcessHandle.Info 引用。接下来,调用command()和其他Info方法,输出它们的值。 如果方法返回null(因为信息不可用),则通过Optional的orElse()方法来返回信息。
 
以下是输出内容,期间可以看到notepad窗口:
 
PROCESS INFORMATION
===================
Process id: 1140
Command: C:PROGRA~1Javajdk-9binjava.exe
Arguments:
Command line:
Start time: 2017-03-02T22:24:40.998Z
Run time duration: 890ms
Owner: jeffjeffrey
 
PROCESS INFORMATION
===================
Process id: 5516
Command: C:WindowsSystem32notepad.exe
Arguments:
Command line:
Start time: 2017-03-02T22:24:41.763Z
Run time duration: 0ms
Owner: jeffjeffrey
 

(编辑:宿州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章