java9系列(四)Process API更新

本文主要研究下JEP 102: Process API Updates

ProcessHandle

/Library/Java/JavaVirtualMachines/jdk-9.0.4.jdk/Contents/Home/lib/src.zip!/java.base/java/lang/ProcessHandle.java

java9新引入了ProcessHandle

/**
 * ProcessHandle identifies and provides control of native processes. Each
 * individual process can be monitored for liveness, list its children,
 * get information about the process or destroy it.
 * By comparison, {@link java.lang.Process Process} instances were started
 * by the current process and additionally provide access to the process
 * input, output, and error streams.
 * 

* The native process ID is an identification number that the * operating system assigns to the process. * The range for process id values is dependent on the operating system. * For example, an embedded system might use a 16-bit value. * Status information about a process is retrieved from the native system * and may change asynchronously; processes may be created or terminate * spontaneously. * The time between when a process terminates and the process id * is reused for a new process is unpredictable. * Race conditions can exist between checking the status of a process and * acting upon it. When using ProcessHandles avoid assumptions * about the liveness or identity of the underlying process. *

* Each ProcessHandle identifies and allows control of a process in the native * system. ProcessHandles are returned from the factory methods {@link #current()}, * {@link #of(long)}, * {@link #children}, {@link #descendants}, {@link #parent()} and * {@link #allProcesses()}. *

* The {@link Process} instances created by {@link ProcessBuilder} can be queried * for a ProcessHandle that provides information about the Process. * ProcessHandle references should not be freely distributed. * *

* A {@link java.util.concurrent.CompletableFuture} available from {@link #onExit} * can be used to wait for process termination, and possibly trigger dependent * actions. *

* The factory methods limit access to ProcessHandles using the * SecurityManager checking the {@link RuntimePermission RuntimePermission("manageProcess")}. * The ability to control processes is also restricted by the native system, * ProcessHandle provides no more access to, or control over, the native process * than would be allowed by a native application. * * @implSpec * In the case where ProcessHandles cannot be supported then the factory * methods must consistently throw {@link java.lang.UnsupportedOperationException}. * The methods of this class throw {@link java.lang.UnsupportedOperationException} * if the operating system does not allow access to query or kill a process. * *

* The {@code ProcessHandle} static factory methods return instances that are * value-based, * immutable and thread-safe. * Use of identity-sensitive operations (including reference equality * ({@code ==}), identity hash code, or synchronization) on these instances of * {@code ProcessHandle} may have unpredictable results and should be avoided. * Use {@link #equals(Object) equals} or * {@link #compareTo(ProcessHandle) compareTo} methods to compare ProcessHandles. * * @see Process * @since 9 */ public interface ProcessHandle extends Comparable { //... }

ProcessHandle提供了对本地进程的控制,可以监控其存活,查找其子进程,查看其信息,甚至销毁它。非常适合耗时较长的进程调用。

实例

查看进程信息

    @Test
    public void testProcessHandle() {
        final ProcessHandle processHandle = ProcessHandle.current();
        final ProcessHandle.Info info = processHandle.info();
        System.out.println("Process info =>");
        System.out.format("PID: %s%n", processHandle.pid());
        info.arguments().ifPresent(args -> System.out.format("Arguments: %s%n", Arrays.toString(args)));
        info.command().ifPresent(command -> System.out.format("Command: %s%n", command));
        info.commandLine()
                .ifPresent(commandLine -> System.out.format("Command line: %s%n", commandLine));
        info.startInstant()
                .ifPresent(startInstant -> System.out.format("Start time: %s%n", startInstant));
        info.totalCpuDuration()
                .ifPresent(cpuDuration -> System.out.format("CPU time: %s%n", cpuDuration));
        info.user().ifPresent(user -> System.out.format("User: %s%n", user));
    }

启动/销毁进程

    @Test
    public void testControlProcess() throws IOException {
        final ProcessBuilder processBuilder = new ProcessBuilder("top")
                .inheritIO();
        ProcessHandle processHandle = processBuilder.start().toHandle();
        final CountDownLatch latch = new CountDownLatch(1);

        processHandle.onExit().whenCompleteAsync((handle, throwable) -> {
            if (throwable == null) {
                System.out.println(handle.pid());
            } else {
                throwable.printStackTrace();
            }
            latch.countDown();
        });
        final Thread shutdownThread = new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (final InterruptedException e) {
                e.printStackTrace();
            }
            if (processHandle.supportsNormalTermination()) {
                processHandle.destroy();
            } else {
                processHandle.destroyForcibly();
            }
        });
        shutdownThread.start();
        try {
            shutdownThread.join();
            latch.await();
        } catch (final InterruptedException e) {
            e.printStackTrace();
        }
    }

小结

java9对process api的最大的更新就是引进了ProcessHandle,可以用来查看进程信息,监控并销毁它。

doc

  • Java 9 新特性概述
  • exploring-java-9 feature9/process
  • java9系列(一)安装及jshell使用
  • java9系列(二)docker运行java9
  • java9系列(三)模块系统精要

你可能感兴趣的:(java9系列(四)Process API更新)