src/share/classes/java/lang/Process.java
Print this page
*** 1,7 ****
/*
! * Copyright (c) 1995, 2008, 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
--- 1,7 ----
/*
! * Copyright (c) 1995, 2012, 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
*** 24,33 ****
--- 24,34 ----
*/
package java.lang;
import java.io.*;
+ import java.util.concurrent.TimeUnit;
/**
* The {@link ProcessBuilder#start()} and
* {@link Runtime#exec(String[],String[],File) Runtime.exec}
* methods create a native process and return an instance of a
*** 89,99 ****
* output stream to be buffered.
*
* @return the output stream connected to the normal input of the
* subprocess
*/
! abstract public OutputStream getOutputStream();
/**
* Returns the input stream connected to the normal output of the
* subprocess. The stream obtains data piped from the standard
* output of the process represented by this {@code Process} object.
--- 90,100 ----
* output stream to be buffered.
*
* @return the output stream connected to the normal input of the
* subprocess
*/
! public abstract OutputStream getOutputStream();
/**
* Returns the input stream connected to the normal output of the
* subprocess. The stream obtains data piped from the standard
* output of the process represented by this {@code Process} object.
*** 115,125 ****
* input stream to be buffered.
*
* @return the input stream connected to the normal output of the
* subprocess
*/
! abstract public InputStream getInputStream();
/**
* Returns the input stream connected to the error output of the
* subprocess. The stream obtains data piped from the error output
* of the process represented by this {@code Process} object.
--- 116,126 ----
* input stream to be buffered.
*
* @return the input stream connected to the normal output of the
* subprocess
*/
! public abstract InputStream getInputStream();
/**
* Returns the input stream connected to the error output of the
* subprocess. The stream obtains data piped from the error output
* of the process represented by this {@code Process} object.
*** 136,146 ****
* input stream to be buffered.
*
* @return the input stream connected to the error output of
* the subprocess
*/
! abstract public InputStream getErrorStream();
/**
* Causes the current thread to wait, if necessary, until the
* process represented by this {@code Process} object has
* terminated. This method returns immediately if the subprocess
--- 137,147 ----
* input stream to be buffered.
*
* @return the input stream connected to the error output of
* the subprocess
*/
! public abstract InputStream getErrorStream();
/**
* Causes the current thread to wait, if necessary, until the
* process represented by this {@code Process} object has
* terminated. This method returns immediately if the subprocess
*** 154,177 ****
* @throws InterruptedException if the current thread is
* {@linkplain Thread#interrupt() interrupted} by another
* thread while it is waiting, then the wait is ended and
* an {@link InterruptedException} is thrown.
*/
! abstract public int waitFor() throws InterruptedException;
/**
* Returns the exit value for the subprocess.
*
* @return the exit value of the subprocess represented by this
* {@code Process} object. By convention, the value
* {@code 0} indicates normal termination.
* @throws IllegalThreadStateException if the subprocess represented
* by this {@code Process} object has not yet terminated
*/
! abstract public int exitValue();
/**
* Kills the subprocess. The subprocess represented by this
* {@code Process} object is forcibly terminated.
*/
! abstract public void destroy();
}
--- 155,270 ----
* @throws InterruptedException if the current thread is
* {@linkplain Thread#interrupt() interrupted} by another
* thread while it is waiting, then the wait is ended and
* an {@link InterruptedException} is thrown.
*/
! public abstract int waitFor() throws InterruptedException;
/**
+ * Causes the current thread to wait, if necessary, until the
+ * subprocess represented by this {@code Process} object has
+ * terminated, or the specified waiting time elapses.
+ *
+ * <p>If the subprocess has already terminated then this method returns
+ * immediately with the value {@code true}. If the process has not
+ * terminated and the timeout value is less than, or equal to, zero, then
+ * this method returns immediately with the value {@code false}.
+ *
+ * <p>The default implementation of this methods polls the {@code exitValue}
+ * to check if the process has terminated. Concrete implementations of this
+ * class are strongly encouraged to override this method with a more
+ * efficient implementation.
+ *
+ * @param timeout the maximum time to wait
+ * @param unit the time unit of the {@code timeout} argument
+ * @return {@code true} if the subprocess has exited and {@code false} if
+ * the waiting time elapsed before the subprocess has exited.
+ * @throws InterruptedException if the current thread is interrupted
+ * while waiting.
+ * @since 1.8
+ */
+ public boolean waitFor(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ long now = System.nanoTime();
+
+ long end = now +
+ (timeout <= 0 ? 0 : TimeUnit.NANOSECONDS.convert(timeout, unit));
+
+ if (end <= 0) // overflow
+ end = Long.MAX_VALUE;
+
+ long rem = end - now;
+ do {
+ try {
+ exitValue();
+ return true;
+ } catch(IllegalThreadStateException ex) {
+ if(rem > 0)
+ Thread.sleep(
+ Math.min(TimeUnit.NANOSECONDS.toMillis(rem) + 1, 100));
+ }
+ rem = end - System.nanoTime();
+ } while(rem > 0);
+ return false;
+ }
+
+ /**
* Returns the exit value for the subprocess.
*
* @return the exit value of the subprocess represented by this
* {@code Process} object. By convention, the value
* {@code 0} indicates normal termination.
* @throws IllegalThreadStateException if the subprocess represented
* by this {@code Process} object has not yet terminated
*/
! public abstract int exitValue();
/**
+ * Kills the subprocess. Whether the subprocess represented by this
+ * {@code Process} object is forcibly terminated or not is
+ * implementation dependent.
+ */
+ public abstract void destroy();
+
+ /**
* Kills the subprocess. The subprocess represented by this
* {@code Process} object is forcibly terminated.
+ *
+ * <p>The default implementation of this method invokes {@link #destroy}
+ * and so may not forcibly terminate the process. Concrete implementations
+ * of this class are strongly encouraged to override this method with a
+ * compliant implementation. {@code Process} objects returned by
+ * {@link ProcessBuilder#start} and {@link Runtime#exec} are of type that
+ * overrides this method and so invoking this method will forcibly terminate
+ * the process.
+ *
+ * <p>Note: The subprocess may not terminate immediately.
+ * i.e. {@code isAlive()} may return true for a brief period
+ * after {@code destroyForcibly()} is called, however this method
+ * may be chained to {@code waitFor()} if needed.
+ *
+ * @return the {@code Process} object representing the
+ * subprocess to be forcibly destroyed.
+ * @since 1.8
*/
! public Process destroyForcibly() {
! destroy();
! return this;
! }
!
! /**
! * Tests whether the subprocess represented by this {@code Process} is
! * alive.
! *
! * @return {@code true} if the subprocess represented by this
! * {@code Process} object has not yet terminated.
! * @since 1.8
! */
! public boolean isAlive() {
! try {
! exitValue();
! return false;
! } catch(IllegalThreadStateException e) {
! return true;
! }
! }
}