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; ! } ! } }