Loom Evades Exception Handling

forax at univ-mlv.fr forax at univ-mlv.fr
Thu Nov 25 22:25:40 UTC 2021


> From: "Eric Kolotyluk" <eric at kolotyluk.net>
> To: "Remi Forax" <forax at univ-mlv.fr>
> Cc: "loom-dev" <loom-dev at openjdk.java.net>
> Sent: Jeudi 25 Novembre 2021 23:16:11
> Subject: Re: Loom Evades Exception Handling

> Thanks for the suggestion Remi, but that does not fix it, it does however result
> in different Exception Handling...

> Actually, my concern is more about the stack traces, and messages, I cannot
> really pinpoint the root cause of the exception. It's like there is missing
> information about the root cause.

> Through another piece of experimental code, I have isolated it to something like
> structuredExecutor.join() ;
> completionHandler.throwIfFailed() ;
> var completedResults = futureResults.map(Future::resultNow).toList() ;
> where the last statement produces

> java.lang.IllegalStateException: Task has not completed
> at java.base/java.util.concurrent.FutureTask.resultNow(FutureTask.java:220)
> at
> java.base/java.util.concurrent.StructuredExecutor$FutureImpl.resultNow(StructuredExecutor.java:726)
> at
> java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
> at java.base/java.util.stream.IntPipeline$1$1.accept(IntPipeline.java:180)
> at
> java.base/java.util.stream.Streams$RangeIntSpliterator.forEachRemaining(Streams.java:104)
> at java.base/java.util.Spliterator$OfInt.forEachRemaining(Spliterator.java:711)
> at
> java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
> at
> java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
> at
> java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575)
> at
> java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
> at
> java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616)
> at
> java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622)
> at
> java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627)
> at net.kolotyluk.loom.Experiment00.main(Experiment00.java:160)

> Which begs the question, how can this throw an exception after the previous two
> statements?

Again, a stream delay the calculation so you call fork() when toList is called after calling join() not before, 
You have to call toList() before calling throwIfFailed(). 

For Alan or Ron, fork() should throw an exception if called after join() ? 

> Cheers, Eric

Rémi 

> On Thu, Nov 25, 2021 at 1:06 PM Remi Forax < [ mailto:forax at univ-mlv.fr |
> forax at univ-mlv.fr ] > wrote:

>> Hi Eric,
>> getRemoteString() returns a Stream, and a Stream delays the call to the
>> intermediary operations to the point where the terminal operation, here
>> forEach(), is called.
>> When forEach() is called, the executor is already closed, so forEach() calls
>> map() that calls fork() that throws an IllegalStateException.

>> I see no issue here, if you return a List instead of a Stream, you will have the
>> behavior I believe you want.

>> regards,
>> Rémi

>> ----- Original Message -----
>> > From: "Eric Kolotyluk" < [ mailto:eric at kolotyluk.net | eric at kolotyluk.net ] >
>>> To: "loom-dev" < [ mailto:loom-dev at openjdk.java.net | loom-dev at openjdk.java.net
>> > ] >
>> > Sent: Jeudi 25 Novembre 2021 21:27:04
>> > Subject: Loom Evades Exception Handling

>> > Yes, that subject line is click-bait, but this is not intuitive to me... Am
>> > I just seeing an incomplete implementation of Project Loom, and this will
>> > be resolved in the future?

>> > public class Experiment06 {

>> > public static void main(String args[]) {
>> > Context.printHeader(Experiment06.class);

>> > try {
>> > getRemoteStrings().forEach(System.out::println);
>> > } catch (ExperimentException e) {
>> > e.printStackTrace();
>> > }
>> > }

>> > static Stream<String> getRemoteStrings() throws ExperimentException {

>> > try (var structuredExecutor = StructuredExecutor.open("Experiment06")) {

>> > // We want complete results, so we won't tolerate failure.
>> > var completionHandler = new StructuredExecutor.ShutdownOnFailure();

>> > var futureResults = IntStream.range(0, 15).mapToObj(item -> {
>> > try {
>> > System.out.printf("item = %d, Thread ID = %s\n",
>> > item, Thread.currentThread());
>> > return structuredExecutor.fork(() -> {
>> > try {
>> > System.out.printf("\ttask = %d, Thread ID
>> > = %s\n", item, Thread.currentThread());
>> > return getRemoteString(item, new
>> > URI(" [ https://server1/foobar.com/item | https://server1/foobar.com/item ] "));
>> > }
>> > catch (Throwable t) {
>> > System.out.printf("TASK EXCEPTION
>> > %s\n\t%s\n\n", t.getMessage(), t.getCause());
>> > t.printStackTrace();
>> > throw t;
>> > }
>> > }, completionHandler);
>> > } catch (Throwable t) {
>> > System.out.printf("SPAWN EXCEPTION %s\n\t%s\n\n",
>> > t.getMessage(), t.getCause());
>> > t.printStackTrace();
>> > throw t;
>> > }
>> > });
>> > structuredExecutor.joinUntil(Instant.now().plusSeconds(10));
>> > completionHandler.throwIfFailed();
>> > return futureResults.map(Future::resultNow);
>> > }
>> > catch (InterruptedException e) {
>> > e.printStackTrace();
>> > throw new ExperimentException(e);
>> > } catch (ExecutionException e) {
>> > e.printStackTrace();
>> > throw new ExperimentException(e);
>> > } catch (TimeoutException e) {
>> > e.printStackTrace();
>> > throw new ExperimentException(e);
>> > } catch (IllegalStateException e) {
>> > e.printStackTrace();
>> > throw new ExperimentException(e);
>> > }
>> > catch (Throwable t) {
>> > t.printStackTrace();
>> > throw new ExperimentException(t);
>> > }
>> > }

>> > static String getRemoteString(int item, URI from) {
>> > return "Item %d from %s".formatted(item, from);
>> > }

>> > static class ExperimentException extends Exception {
>> > ExperimentException(Throwable cause) {
>> > super(cause);
>> > }
>> > }
>> > }

>> > where I get

>> > [image: image.png]


>> > (Experiment06.java:50) is

>> > return structuredExecutor.fork(() -> {

>> > (Experiment06.java:34) is

>> > getRemoteStrings().forEach(System.out::println);

>> > Is there some way I can actually find out more from the Exception handling,
>> > or other techniques?

>> > Cheers, Eric


More information about the loom-dev mailing list