Improve `finally` block exception handling
David Holmes
david.holmes at oracle.com
Mon Apr 18 04:40:58 UTC 2022
Hello,
On 18/04/2022 5:43 am,
some-java-user-99206970363698485155 at vodafonemail.de wrote:
>
> Hello,
>
> are there any plans to improve exception handling in combination with `finally` blocks?
I'm not aware of anything, nor what that anything could realistically
be. You make only one suggestion that has a little merit.
> Currently, when a `finally` block does not complete normally, the original exception is
> silently discarded (as described in the JLS). This behavior is error-prone, not obvious
> at all, and has been criticized in the past a lot. An example for this is https://stackoverflow.com/q/48088
> and the linked posts there.
The behaviour of try/catch/finally is not "obvious at all", you have to
read what it means and when you do that you clearly see what happens
regarding exceptions.
> While javac warns you about this issue when using `-Xlint:finally`, it is only a warning
> and not even enabled by default.
>
> Are there any plans to forbid usage of `break`, `continue`, `yield` and `return` in
> `finally` blocks?
Why would we do that? What would that gain?
> Switch expressions have already set a precedent for this by not allowing to leave the
> switch expression by something other than a `throw` or `yield` statement, trying to use
> for example a `return` statement causes a compilation error.
That is because it is an _expression_ - expressions have to have
different language rules to statements. There is no connection to a
finally block.
> Similarly for `throw` and any implicitly thrown exceptions, is there a plan to at least
> add the original exception as suppressed one to the newly thrown?
That suggestion is not completely without merit, but nor is it a
"slam-dunk" obvious thing to do. The semantic implications of the
exceptions matter, and semantics come from the programmers intent.
There's no reasonable way to automagically determine that when an
exception is created that another exception (that led to the finally
block) should be inserted as a "suppressed exception". That would
actually be completely wrong to do in many circumstances you would
instead need to act when the exception would terminate the finally block
and then add the original exception as the "suppressed" exception. But
really the programmer is in the best position to decide how exceptions
need to be handled.
> Of course one could argue that the same applies to `catch` clauses whose body accidentally
> causes an exception which discards the caught one. However the main difference is that
Yes exactly the same.
> there, only a specific exception type is caught (and discarded), whereas for `finally`
> exceptions of _any_ type are discarded. It could also be argued that adding suppressed
We have multi-catch now so that argument is somewhat weaker.
> exceptions decreases performance or causes memory leaks, but one the other hand
> this behavior was explicitly included try-with-resources statements, most likely because the
> value this adds was considered more important than any performance issues this
> might cause.
try-with-resources added support for suppressed exceptions because the
automatic closing of the resource could throw an exception, and that had
to be factored in to the whole mechanism.
> Also, it is important to keep in mind that this affects _all_ Throwable types, including
> VM errors which you really should not catch, and which due to a `finally` block might
> silently be discarded. Most, if not all, code in which a `finally` does not complete
> normally does not seem to consider this.
That is true. But for me a finally block is intended to be quite small
and succint and should be written from the perspective of "an unexpected
exception has occurred, what it is it critical for me to do before
leaving the current scope".
> This is also not a theoretical problem; this issue exists in multiple open source projects,
> potentially even in the JDK itself.
> Often the code can be rewritten by either moving the complete code or parts of it
> outside of the `finally` block, or by introducing a local variable to hold the result and
> to return that after the `finally` block.
>
> What do you think about this topic?
I think there is no clear and obvious solution that the language can put
in place here.
Just my personal 2c.
Cheers,
David
> Is backward compatibility a concern? If so, can you provide an example where using such
> a pattern provides any notable advantages which justify the potential loss of thrown
> VM errors or exceptions.
>
> Kind regards
>
>
>
More information about the core-libs-dev
mailing list