diff --git a/src/java.base/share/classes/java/lang/Process.java b/src/java.base/share/classes/java/lang/Process.java index 756705285d966..3da1809f4ac20 100644 --- a/src/java.base/share/classes/java/lang/Process.java +++ b/src/java.base/share/classes/java/lang/Process.java @@ -32,6 +32,7 @@ import java.lang.ProcessBuilder.Redirect; import java.nio.charset.Charset; import java.nio.charset.UnsupportedCharsetException; +import java.time.Duration; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ForkJoinPool; @@ -456,14 +457,54 @@ public final BufferedWriter outputWriter(Charset charset) { * @since 1.8 */ public boolean waitFor(long timeout, TimeUnit unit) - throws InterruptedException - { - long remainingNanos = unit.toNanos(timeout); // throw NPE before other conditions + throws InterruptedException { + Objects.requireNonNull(unit, "unit"); // throw NPE before other conditions + if (hasExited()) return true; if (timeout <= 0) return false; + return waitForNanos(unit.toNanos(timeout)); + } + + /** + * Causes the current thread to wait, if necessary, until the + * process represented by this {@code Process} object has + * terminated, or the specified waiting duration elapses. + * + *
If the process has already terminated then this method returns + * immediately with the value {@code true}. If the process has not + * terminated and the duration is not positive, then + * this method returns immediately with the value {@code false}. + * + *
The default implementation of this method 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 duration the maximum duration to wait; if not positive,
+ * this method returns immediately.
+ * @return {@code true} if the process has exited and {@code false} if
+ * the waiting duration elapsed before the process has exited.
+ * @throws InterruptedException if the current thread is interrupted
+ * while waiting.
+ * @throws NullPointerException if duration is null
+ * @since 24
+ */
+ public boolean waitFor(Duration duration)
+ throws InterruptedException {
+ Objects.requireNonNull(duration, "duration"); // throw NPE before other conditions
+
+ if (hasExited())
+ return true;
+ if (duration.isZero() || duration.isNegative())
+ return false;
+
+ return waitForNanos(TimeUnit.NANOSECONDS.convert(duration));
+ }
+
+ private boolean waitForNanos(long remainingNanos) throws InterruptedException {
long deadline = System.nanoTime() + remainingNanos;
do {
Thread.sleep(Math.min(TimeUnit.NANOSECONDS.toMillis(remainingNanos) + 1, 100));
diff --git a/test/jdk/java/lang/Process/WaitForDuration.java b/test/jdk/java/lang/Process/WaitForDuration.java
new file mode 100644
index 0000000000000..353ab8cc2d591
--- /dev/null
+++ b/test/jdk/java/lang/Process/WaitForDuration.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2024, 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8336479
+ * @summary Tests for Process.waitFor(Duration)
+ * @run junit WaitForDuration
+ */
+
+import java.io.IOException;
+import java.time.Duration;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import static org.junit.jupiter.api.Assertions.*;
+
+public class WaitForDuration {
+ static Stream