/* * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.lang; import java.time.Duration; import java.time.Instant; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.stream.Stream; /** * 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 #allChildren}, {@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 1.9 */ public interface ProcessHandle extends Comparable { /** * Returns the native process ID of the process. The native process ID is an * identification number that the operating system assigns to the process. * The operating system may reuse the process ID after a process terminates. * Use {@link #equals(Object) equals} or * {@link #compareTo(ProcessHandle) compareTo} to compare ProcessHandles. * * @return the native process ID of the process * @throws UnsupportedOperationException if the implementation * does not support this operation */ long getPid(); /** * Returns an {@code Optional} for an existing native process. * * @param pid a native process ID * @return an {@code Optional} of the PID for the process; * the {@code Optional} is empty if the process does not exist * @throws SecurityException if a security manager has been installed and * it denies RuntimePermission("manageProcess") * @throws UnsupportedOperationException if the implementation * does not support this operation */ public static Optional of(long pid) { return ProcessHandleImpl.get(pid); } /** * Returns a ProcessHandle for the current process. The ProcessHandle cannot be * used to destroy the current process, use {@link System#exit System.exit} instead. * * @return a ProcessHandle for the current process * @throws SecurityException if a security manager has been installed and * it denies RuntimePermission("manageProcess") * @throws UnsupportedOperationException if the implementation * does not support this operation */ public static ProcessHandle current() { return ProcessHandleImpl.current(); } /** * Returns an {@code Optional} for the parent process. * Note that Processes in a zombie state usually don't have a parent. * * @return an {@code Optional} of the parent process; * the {@code Optional} is empty if the child process does not have a parent * or if the parent is not available, possibly due to operating system limitations * @throws SecurityException if a security manager has been installed and * it denies RuntimePermission("manageProcess") */ Optional parent(); /** * Returns a snapshot of the current direct children of the process. * A process that is {@link #isAlive not alive} has zero children. *

* Note that processes are created and terminate asynchronously. * There is no guarantee that a process is {@link #isAlive alive}. * * * @return a Stream of ProcessHandles for processes that are direct children * of the process * @throws SecurityException if a security manager has been installed and * it denies RuntimePermission("manageProcess") */ Stream children(); /** * Returns a snapshot of the current direct and indirect children of the process. * A process that is {@link #isAlive not alive} has zero children. *

* Note that processes are created and terminate asynchronously. * There is no guarantee that a process is {@link #isAlive alive}. * * * @return a Stream of ProcessHandles for processes that are direct and * indirect children of the process * @throws SecurityException if a security manager has been installed and * it denies RuntimePermission("manageProcess") */ Stream allChildren(); /** * Returns a snapshot of all processes visible to the current process. *

* Note that processes are created and terminate asynchronously. There * is no guarantee that a process in the stream is alive or that no other * processes may have been created since the inception of the snapshot. * * * @return a Stream of ProcessHandles for all processes * @throws SecurityException if a security manager has been installed and * it denies RuntimePermission("manageProcess") * @throws UnsupportedOperationException if the implementation * does not support this operation */ static Stream allProcesses() { return ProcessHandleImpl.children(0); } /** * Returns a snapshot of information about the process. * *

An {@code Info} instance has various accessor methods that return * information about the process, if the process is alive and the * information is available. * * @return a snapshot of information about the process, always non-null */ Info info(); /** * Information snapshot about the process. * The attributes of a process vary by operating system and are not available * in all implementations. Information about processes is limited * by the operating system privileges of the process making the request. * The return types are {@code Optional} allowing explicit tests * and actions if the value is available. * @since 1.9 */ public interface Info { /** * Returns the executable pathname of the process. * * @implNote Note that the returned pathname may be truncated on some * platforms due to system limitations. It may also only * contain the name of the executable without the full path * information. * * @return an {@code Optional} of the executable pathname * of the process */ public Optional command(); /** * Returns an array of Strings of the arguments of the process. * * @implNote Note that the argument list may be truncated on some * platforms due to system limitations. * * @return an {@code Optional} of the arguments of the process */ public Optional arguments(); /** * Returns the start time of the process. * * @return an {@code Optional} of the start time of the process */ public Optional startInstant(); /** * Returns the total cputime accumulated of the process. * * @return an {@code Optional} for the accumulated total cputime */ public Optional totalCpuDuration(); /** * Return the user of the process. * * @return an {@code Optional} for the user of the process */ public Optional user(); } /** * Returns a {@code CompletableFuture} for the termination * of the process. * The {@link java.util.concurrent.CompletableFuture} provides the ability * to trigger dependent functions or actions that may be run synchronously * or asynchronously upon process termination. * When the process terminates the CompletableFuture is * {@link java.util.concurrent.CompletableFuture#complete completed} regardless * of the exit status of the process. * The {@code onExit} method can be called multiple times to invoke * independent actions when the process exits. *

* Calling {@code onExit().get()} waits for the process to terminate and returns * the ProcessHandle. The future can be used to check if the process is * {@link java.util.concurrent.CompletableFuture#isDone done} or to * {@link java.util.concurrent.Future#get() wait} for it to terminate. * {@link java.util.concurrent.Future#cancel(boolean) Cancelling} * the CompleteableFuture does not affect the Process. *

* If the process is {@link #isAlive not alive} the {@link CompletableFuture} * returned has been {@link java.util.concurrent.CompletableFuture#complete completed}. * * @return a new {@code CompletableFuture} for the ProcessHandle * * @throws IllegalStateException if the process is the current process */ CompletableFuture onExit(); /** * Returns {@code true} if the implementation of {@link #destroy} * normally terminates the process. * Returns {@code false} if the implementation of {@code destroy} * forcibly and immediately terminates the process. * * @return {@code true} if the implementation of {@link #destroy} * normally terminates the process; * otherwise, {@link #destroy} forcibly terminates the process */ boolean supportsNormalTermination(); /** * Requests the process to be killed. * Whether the process represented by this {@code ProcessHandle} object is * {@link #supportsNormalTermination normally terminated} or not is * implementation dependent. * Forcible process destruction is defined as the immediate termination of the * process, whereas normal termination allows the process to shut down cleanly. * If the process is not alive, no action is taken. * The operating system access controls may prevent the process * from being killed. *

* The {@link java.util.concurrent.CompletableFuture} from {@link #onExit} is * {@link java.util.concurrent.CompletableFuture#complete completed} * when the process has terminated. *

* Note: The process may not terminate immediately. * For example, {@code isAlive()} may return true for a brief period * after {@code destroy()} is called. * * @return {@code true} if termination was successfully requested, * otherwise {@code false} * @throws IllegalStateException if the process is the current process */ boolean destroy(); /** * Requests the process to be killed forcibly. * The process represented by this {@code ProcessHandle} object is * forcibly terminated. * Forcible process destruction is defined as the immediate termination of the * process, whereas normal termination allows the process to shut down cleanly. * If the process is not alive, no action is taken. * The operating system access controls may prevent the process * from being killed. *

* The {@link java.util.concurrent.CompletableFuture} from {@link #onExit} is * {@link java.util.concurrent.CompletableFuture#complete completed} * when the process has terminated. *

* Note: The process may not terminate immediately. * For example, {@code isAlive()} may return true for a brief period * after {@code destroyForcibly()} is called. * * @return {@code true} if termination was successfully requested, * otherwise {@code false} * @throws IllegalStateException if the process is the current process */ boolean destroyForcibly(); /** * Tests whether the process represented by this {@code ProcessHandle} is alive. * Process termination is implementation and operating system specific. * The process is considered alive as long as the PID is valid. * * @return {@code true} if the process represented by this * {@code ProcessHandle} object has not yet terminated */ boolean isAlive(); /** * Returns a hash code value for this ProcessHandle. * The hashcode value follows the general contract for {@link Object#hashCode()}. * The value is a function of the {@link #getPid getPid()} value and * may be a function of additional information to uniquely identify the process. * If two ProcessHandles are equal according to the {@link #equals(Object) equals} * method, then calling the hashCode method on each of the two objects * must produce the same integer result. * * @return a hash code value for this object */ @Override int hashCode(); /** * Returns {@code true} if {@code other} object is non-null, is of the * same implementation, and represents the same system process; * otherwise it returns {@code false}. * @implNote * It is implementation specific whether ProcessHandles with the same PID * represent the same system process. ProcessHandle implementations * should contain additional information to uniquely identify the process. * For example, the start time of the process could be used * to determine if the PID has been re-used. * The implementation of {@code equals} should return {@code true} for two * ProcessHandles with the same PID unless there is information to * distinguish them. * * @param other another object * @return {@code true} if the {@code other} object is non-null, * is of the same implementation class and represents * the same system process; otherwise returns {@code false} */ @Override boolean equals(Object other); /** * Compares this ProcessHandle with the specified ProcessHandle for order. * The order is not specified, but is consistent with {@link Object#equals}, * which returns {@code true} if and only if two instances of ProcessHandle * are of the same implementation and represent the same system process. * Comparison is only supported among objects of same implementation. * If attempt is made to mutually compare two different implementations * of {@link ProcessHandle}s, {@link ClassCastException} is thrown. * * @param other the ProcessHandle to be compared * @return a negative integer, zero, or a positive integer as this object * is less than, equal to, or greater than the specified object. * @throws NullPointerException if the specified object is null * @throws ClassCastException if the specified object is not of same class * as this object */ @Override int compareTo(ProcessHandle other); }