src/share/classes/java/lang/Process.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
+ * 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,10 +24,11 @@
  */
 
 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,11 +90,11 @@
      * output stream to be buffered.
      *
      * @return the output stream connected to the normal input of the
      *         subprocess
      */
-    abstract public OutputStream getOutputStream();
+    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,11 +116,11 @@
      * input stream to be buffered.
      *
      * @return the input stream connected to the normal output of the
      *         subprocess
      */
-    abstract public InputStream getInputStream();
+    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,11 +137,11 @@
      * input stream to be buffered.
      *
      * @return the input stream connected to the error output of
      *         the subprocess
      */
-    abstract public InputStream getErrorStream();
+    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,24 +155,135 @@
      * @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;
+    public abstract int waitFor() throws InterruptedException;
 
     /**
+     * Causes the current thread to wait until the subprocess represented by 
+     * this {@code Process} has terminated, unless the thread is 
+     * {@linkplain Thread#interrupt interrupted}, or the specified waiting time
+     * elapses.
+     *
+     * <p>If the subprocess has already exited then this method returns 
+     * immediately with the value {@code true}.  If the process has not exited
+     * and the timeout is zero then this method returns immediately with the
+     * value {@code false}
+     *
+     * <p>If the subprocess has not exited then the current
+     * thread becomes disabled for thread scheduling purposes and lies
+     * dormant until one of three things happen:
+     * <ul>
+     * <li>The subprocess exits; or
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+     * the current thread; or
+     * <li>The specified waiting time elapses.
+     * </ul>
+     *
+     * <p>If the subprocess terminates then the method returns with the
+     * value {@code true}.
+     * 
+     * <p>If the current thread:
+     * <ul>
+     * <li>has its interrupted status set on entry to this method; or
+     * <li>is {@linkplain Thread#interrupt interrupted} while waiting,
+     * </ul>
+     * then {@link InterruptedException} is thrown and the current thread's
+     * interrupted status is cleared.
+     *
+     * <p>If the specified waiting time elapses and the subprocess has not 
+     * exited then the value {@code false} is returned.  If the time is less 
+     * than or equal to zero, the method will not wait at all.
+     *
+     * <p>The default implementation of this method polls {@code exitValue()} 
+     * and repeatedly catches the resulting {@code IllegalThreadStateException} 
+     * until the {@code timeout} expires or the subprocess is terminated.
+     * Implementations are strongly encouraged to override this method.
+     *
+     * @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 + 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(rem < 100 ? rem : 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
      */
-    abstract public int exitValue();
+    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 is implementation dependent as to whether it terminates the 
+     * process forcibly or not.  Implementations are strongly encouraged to 
+     * override this method.
+     *
+     * <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
      */
-    abstract public void destroy();
+    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;
+        }
+    }
 }