-
Bug
-
Resolution: Unresolved
-
P3
-
22, 25
-
generic
-
generic
A DESCRIPTION OF THE PROBLEM :
When submitting a Callable to a ForkJoinPool and cancel the returned Future afterwards, getting the result no longer throws a CancellationException. Instead, an ExecutionException is thrown, wrapping the CancellationException. This contradicts the Future#get() specification.
This worked well in Java 17, but is broken in Java 24 (maybe in earlier releases as well).
REGRESSION : Last worked in version 17.0.16
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Submit a Callable to a ForkJoinPool and cancel the returned Future.
Calling get() on the Future should result in a CancellationException, according to the Future specification.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Calling 'task.get()' should result in a CancellationException.
ACTUAL -
Calling 'task.get()' results in an ExecutionException, wrapping a CancellationException.
---------- BEGIN SOURCE ----------
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
public class ForkJoinPoolTest {
public static void main(String[] args) throws Exception {
ForkJoinPool pool = new ForkJoinPool();
final ForkJoinTask<?> task = pool.submit(() -> {
try {
Thread.sleep(1000); // Simulate some work
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
new Thread(() -> {
try {
Thread.sleep(100);
} catch (InterruptedException aE) {
}
task.cancel(true); // Cancel the task
}).start();
task.get(); // This should throw CancellationException
}
}
---------- END SOURCE ----------
When submitting a Callable to a ForkJoinPool and cancel the returned Future afterwards, getting the result no longer throws a CancellationException. Instead, an ExecutionException is thrown, wrapping the CancellationException. This contradicts the Future#get() specification.
This worked well in Java 17, but is broken in Java 24 (maybe in earlier releases as well).
REGRESSION : Last worked in version 17.0.16
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Submit a Callable to a ForkJoinPool and cancel the returned Future.
Calling get() on the Future should result in a CancellationException, according to the Future specification.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Calling 'task.get()' should result in a CancellationException.
ACTUAL -
Calling 'task.get()' results in an ExecutionException, wrapping a CancellationException.
---------- BEGIN SOURCE ----------
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
public class ForkJoinPoolTest {
public static void main(String[] args) throws Exception {
ForkJoinPool pool = new ForkJoinPool();
final ForkJoinTask<?> task = pool.submit(() -> {
try {
Thread.sleep(1000); // Simulate some work
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
new Thread(() -> {
try {
Thread.sleep(100);
} catch (InterruptedException aE) {
}
task.cancel(true); // Cancel the task
}).start();
task.get(); // This should throw CancellationException
}
}
---------- END SOURCE ----------