Loom Evades Exception Handling

Eric Kolotyluk eric at kolotyluk.net
Thu Nov 25 22:16:11 UTC 2021


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

[image: image.png]

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?

Cheers, Eric

On Thu, Nov 25, 2021 at 1:06 PM Remi Forax <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" <eric at kolotyluk.net>
> > To: "loom-dev" <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"));
> >                        }
> >                        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