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