Future.resultNow()

Ron Pressler ron.pressler at oracle.com
Sun Nov 21 11:28:04 UTC 2021


The checked exception thrown by resultNow always indicates a bug in the program, as resultNow must only be called when the program is in a state where it is *guaranteed* not to throw: either after checking Future.state() or after StructuredExecutor.join() followed by handling exceptions with the completion handler.

That is why the exception only contains enough information to indicate the source of the bug — stating that the task threw an exception that it was cancelled — and not any information that could be used to correctly handle it, as there is no right way to handle it. If it’s thrown, the program is wrong: it calls the method while in an incorrect state. Calling resultNow or exceptionNow asserts that you know that at this point in the program, they will not throw. Hypothetically, they could have thrown, say, an AssertionError, except IllegalStateException is already the common practice in precisely that kind of situation. In any event, in a correct program, these methods never throw (and, in general, ISEs and similar exceptions, like IllegalMonitorStateExceptions, are never thrown in correct programs).

I don’t think that wrapping the underlying exception, if there is one, would be helpful in pinpointing the bug. If the ISE tells you it’s caused by an exception, you know you need to correct the program by adding code to handle exceptions or filter them. What the original exception was is irrelevant.

So, to answer Rémi’s question, yes we are afraid of precisely that, that including the original exception might lead people to try handling it.

— Ron

> On 20 Nov 2021, at 23:00, Alex Otenko <oleksandr.otenko at gmail.com> wrote:
> 
> What is the bug in this case? The exception thrown by the task, the caller
> not checking the task is done, or that it is done with an exception?
> 
> The API owners seem to disagree with me, but I don't think any of those is
> a bug. I polled the task - I got no result now, I moved on. Especially
> since a get() would already do the right thing, including throwing the
> exception, a non-blocking method feels like it should be more like
> BlockingQueue.poll compared to BlockingQueue.take.
> 
> Alex
> 
> On Sat, 20 Nov 2021, 21:57 , <forax at univ-mlv.fr> wrote:
> 
>> 
>> 
>> ------------------------------
>> 
>> *From: *"Alex Otenko" <oleksandr.otenko at gmail.com>
>> *To: *"Remi Forax" <forax at univ-mlv.fr>
>> *Cc: *"loom-dev" <loom-dev at openjdk.java.net>
>> *Sent: *Samedi 20 Novembre 2021 22:49:01
>> *Subject: *Re: Future.resultNow()
>> 
>> No, I am not afraid :)
>> 
>> I just think introspecting the chain of causes is brittle - in the sense
>> that it relies on a specific implementation wrapping the exception in a
>> particular way.
>> 
>> 
>> As Brian said, IllegalStateException is not an exception you should ever
>> catch like NPE or AIOOBE, it's equivalent to a
>> ReadTheFuckingManualException,
>> it's an error raised because the developer has misunderstood how the API
>> works, so providing the cause (maybe as an error message) helps to fix the
>> bug.
>> 
>> 
>> Alex
>> 
>> 
>> Rémi
>> 
>> 
>> On Sat, 20 Nov 2021, 21:44 , <forax at univ-mlv.fr> wrote:
>> 
>>> 
>>> 
>>> ------------------------------
>>> 
>>> *From: *"Alex Otenko" <oleksandr.otenko at gmail.com>
>>> *To: *"Remi Forax" <forax at univ-mlv.fr>
>>> *Cc: *"loom-dev" <loom-dev at openjdk.java.net>
>>> *Sent: *Samedi 20 Novembre 2021 21:10:59
>>> *Subject: *Re: Future.resultNow()
>>> 
>>> I wouldn't expect it to contain the exact cause (why the cause, and not
>>> the cause of the cause of the cause), and expect exceptionNow to be the
>>> source of truth.
>>> 
>>> 
>>> Are you afraid that people will catch the ISE to extract the exception
>>> instead of using Future.get() and catch the ExecutionException to extract
>>> the exception ?
>>> This is a valid concern, ExecutionException is checked and ISE is not, if
>>> you provide two ways to get the same thing, i believe people will go with
>>> the method that throws an unchecked exception.
>>> 
>>> So perhaps, instead of using the cause field, the error message of the
>>> ISE should contain a string version of the exception like toString() does.
>>> 
>>> 
>>> Alex
>>> 
>>> 
>>> Rémi
>>> 
>>> 
>>> On Sat, 20 Nov 2021, 19:14 Remi Forax, <forax at univ-mlv.fr> wrote:
>>> 
>>>> If a callable throws an exception, Future.resultNow() throws an ISE but
>>>> forget to set the resulting exception as the cause of the ISE.
>>>> 
>>>> regards,
>>>> Rémi
>>>> 
>>> 
>> 



More information about the loom-dev mailing list