Multi-catch/final rethrow
Stephen Colebourne
scolebourne at joda.org
Tue May 4 08:42:52 PDT 2010
Agreed - that is the perspective from a compiler writer. Its just
"better flow analysis". But most developers don't understand that.
The new code says "throw", the type it is throwing is "Exception", yet
it isn't declared in the method signature - the exception disappears
into thin air! (at least in the eyes of many devs).
There be a puzzler here...
Stephen
On 4 May 2010 16:27, Jonathan Gibbons <jonathan.gibbons at oracle.com> wrote:
> Stephen,
>
> Regarding your example, there is no new syntax involved. If you take your
> "process" method, change "Exception" to "RuntimeException", and wrap it in a
> class, you'll find it compiles just fine with JDK 6, so it should not be too
> unfamiliar even to some of you "old hands".
>
> $ more Test.java
> class Test {
>
> public void process() {
> try {
> System.out.println("No exception thrown here...");
> } catch (final RuntimeException ex) {
> throw ex;
> }
> }
>
> }
> $ /opt/jdk/1.6.0/bin/javac Test.java
> $
>
> The only thing that has changed, as regards your example as written, is that
> now javac can do better flow analysis of the try block to determine that no
> checked exceptions can be thrown, and so none need to be listed in the
> throws clause of the method declaration.
>
> -- Jon
>
>
>
>
>
> Stephen Colebourne wrote:
>
> While I'm sure many will welcome these additions, I must be clear that
> I find the syntax approach used for final rethrow to be undesirable.
> The change that the developer makes (adding 'final') is too subtle and
> unconnected to the task at hand.
>
> It also leads to some odd behaviour (assuming I've understood the spec):
>
> public void process() {
> try {
> System.out.println("No exception thrown here...");
> } catch (final Exception ex) {
> throw ex;
> }
> }
>
> Here, we throw an exception without it appearing in the throws clause
> of the method. I'm of the opinion that will be pretty confusing to
> newcomers (and even some of us old-hands).
>
> Note that I don't have a great alternative. I suspect a 'rethrow'
> keyword would probably be best (dovetailed with the 'final' part for
> obvious reasons). Given that we can't use a new keyword, perhaps the
> 'throws final' might work.
>
> Stephen
>
>
> On 4 May 2010 01:25, <joe.darcy at oracle.com> wrote:
>
>
> Greetings,
>
> As alluded to as a possibility previously [1], I'm happy to announce
> that improved exception handling with multi-catch and final rethrow will
> be part of an upcoming JDK 7 build. Improved exception handling is
> joining other Project Coin features implemented in the repository after
> successful experiences with a multi-catch implementation developed by
> Maurizio Cimadamore.
>
> Maurizio's work also revealed and corrected a flaw in the originally
> proposed static analysis for the set of exception that can be rethrown [2]:
>
>
>
> [a] final catch parameter is treated as throwing precisely those
> exception types that
> - the try block can throw,
> - no previous catch clause handles, and
> - is a subtype of one of the types in the declaration of the catch
> parameter
>
>
> Consider a final rethrow statement as below where the dynamic class of a
> thrown exception differs from the static type (due to a cast in this case):
>
> class Neg04 {
> static class A extends Exception {}
> static class B extends Exception {}
>
> void test(boolean b1, boolean b2) throws B {
> try {
> if (b1) {
> throw new A();
> } else if (b2) {
> throw new B();
> } else {
> throw (Throwable)new Exception();
> }
> }
> catch (A e) {}
> catch (final Exception e) {
> throw e;
> }
> catch (Throwable t) {}
> }
> }
>
> The set of exceptions thrown by the try block is computed {A, B,
> Throwable}; therefore, the set of exceptions that can be rethrown is the
> set of exceptions from the try block:
>
> * minus A, handled by a previous catch clause, giving {B, Throwable}
> * minus Throwable since Throwable is not a subtype of one of the types
> declared for the catch parameter (just Exception in this case), leaving
> just {B}
>
> However, if an Exception is thrown from the try it should be caught in
> the "catch(final Exception e)" clause even if the exception is cast to
> Throwable since catch clauses work based on the runtime class of the
> exceptions being thrown.
>
> To address this, the third clause is changed to
>
>
>
> - is a subtype/supertype of one of the types in the declaration of the
> catch parameter
>
>
> More formally, this clause covers computing a join over the set of
> thrown exceptions, eliminating subtypes. In the example above
> {Throwable} is computed as the set of exceptions being throwable from
> the try block. This is then intersected with the exceptions that can be
> caught by the try block, resulting in {Exception}, a properly sound result.
>
> Very general exception types being thrown by a try block would reduce
> the utility of multi-catch since only imprecise information would be
> available. Fortunately, from analyzing the JDK sources, throwing a
> statically imprecise exception seems rare, indicating multi-catch with
> the amended specification should still be very be helpful in practice.
>
> Today the adventurous can apply a changest [3] to a copy of the JDK 7
> langtrools repository and build get a javac supporting this feature.
> Otherwise, the change will appear in promoted JDK 7 builds in due
> course. [4]
>
> -Joe
>
> [1] "Project Coin: Post-Devoxx Update, closures and exception handling,"
> http://blogs.sun.com/darcy/entry/projec_coin_post_devoxx_closures
>
> [2] "Improved Exception Handling for Java,"
> http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000003.html
>
> [3] http://hg.openjdk.java.net/jdk7/tl/langtools/rev/a6f2911a7c55
>
> [4] http://download.java.net/jdk7/binaries/
>
>
>
>
>
>
More information about the coin-dev
mailing list