Lambda and multi-catch
    Ivan Babanin 
    babanin at gmail.com
       
    Fri Mar  7 23:50:38 UTC 2014
    
    
  
> 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).
I got source from http://hg.openjdk.java.net/jdk8u/jdk8u 
After a brief analysis, I found the problem in LambdaToMethod.
visitVarDef(...):438. 
Tree translator creates JCVariableDecl (line 444) and ignores vartype of
original tree, that's why Gen. genCatch(...)  generate only single catch in
exception table.
I think my code (surrounded by comments) will fix this bug:
        LambdaTranslationContext lambdaContext =
(LambdaTranslationContext)context;
        if (context != null &&
lambdaContext.getSymbolMap(LOCAL_VAR).containsKey(tree.sym)) {
            JCExpression init = translate(tree.init);
            int prevPos = make.pos;
            try {
                result =
make.at(tree).VarDef((VarSymbol)lambdaContext.getSymbolMap(LOCAL_VAR).get(tr
ee.sym), init);
	// Copy vartype from original tree for variables with multiple types
                if ((result != null) && tree.vartype.hasTag(TYPEUNION)) {
                    ((JCVariableDecl) result).vartype = tree.vartype;
                }
	//
            } finally {
                make.at(prevPos);
            }
sy,
Ivan
    
    
More information about the lambda-dev
mailing list