Lambda and multi-catch

David M. Lloyd david.lloyd at redhat.com
Thu Mar 6 12:46:41 UTC 2014


On 03/06/2014 05:29 AM, Remi Forax wrote:
> A colleague of mine have find a hairy bug,
> here is a simple code to reproduce it.
>
> import java.io.IOException;
>
> public class FunWithMultiCatch {
>    public static void main(String[] args) {
>      Runnable r = () -> {
>        try {
>          Object o = null;
>          o.getClass();
>          throw new IOException();
>        } catch(IOException | IllegalArgumentException e) {
>          System.out.println("KO !");
>        } catch(RuntimeException e) {
>          System.out.println("OK !");
>        }
>      };
>      r.run();
>    }
> }
>
> It prints 'KO !' :(
> The problem can be reproduced for any multi-catch inside a lambda,
> the exception table is clearly wrong, the IOException and IAE are merged
> to their common supertype (java.lang.Exception).
>
> private static void lambda$main$0();
>      Code:
>         0: aconst_null
>         ...
>        14: athrow
>        15: astore_0
>        16: getstatic     #8                  // Field
> java/lang/System.out:Ljava/io/PrintStream;
>        19: ldc           #9                  // String OK !
>        21: invokevirtual #10                 // Method
> java/io/PrintStream.println:(Ljava/lang/String;)V
>        24: goto          36
>        27: astore_0
>        28: getstatic     #8                  // Field
> java/lang/System.out:Ljava/io/PrintStream;
>        31: ldc           #12                 // String KO !
>        33: invokevirtual #10                 // Method
> java/io/PrintStream.println:(Ljava/lang/String;)V
>        36: return
>      Exception table:
>         from    to  target type
>             0    15    15   Class
> java/lang/Exception                            <------------ Oops
>             0    15    27   Class java/lang/RuntimeException
>
> The current workaround is to not use a multi-catch in a lambda.
>
> It seems that some version of Eclipse had the same issue but it's fixed
> with the one I use (from 21 feb).

I've noticed that the Oracle JDK 7 also uses the common supertype 
instead of two catch clauses, which caused trouble for my seven2six 
bytecode translator when a new exception common supertype was introduced 
in the hierarchy in JDK 7 (but it could cause trouble in other, normal 
cases of upgrade as well).

I figured this was some form of optimization.  But doesn't it make more 
sense to rely on the JVM to optimize this case?  A paranoid fellow might 
interpret it as a deliberate move to make binary compatibility even more 
difficult than it is today.

Or is it a mistake that the JDK ever did this?
-- 
- DML


More information about the compiler-dev mailing list