1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Dec 12 19:19:07 2013 -0800 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Fri Dec 13 14:13:03 2013 +0000 1.3 @@ -2590,15 +2590,61 @@ 1.4 } 1.5 } 1.6 1.7 + /* Map to hold 'fake' clinit methods. If a lambda is used to initialize a 1.8 + * static field and that lambda has type annotations, these annotations will 1.9 + * also be stored at these fake clinit methods. 1.10 + * 1.11 + * LambdaToMethod also use fake clinit methods so they can be reused. 1.12 + * Also as LTM is a phase subsequent to attribution, the methods from 1.13 + * clinits can be safely removed by LTM to save memory. 1.14 + */ 1.15 + private Map<ClassSymbol, MethodSymbol> clinits = new HashMap<>(); 1.16 + 1.17 + public MethodSymbol removeClinit(ClassSymbol sym) { 1.18 + return clinits.remove(sym); 1.19 + } 1.20 + 1.21 + /* This method returns an environment to be used to attribute a lambda 1.22 + * expression. 1.23 + * 1.24 + * The owner of this environment is a method symbol. If the current owner 1.25 + * is not a method, for example if the lambda is used to initialize 1.26 + * a field, then if the field is: 1.27 + * 1.28 + * - an instance field, we use the first constructor. 1.29 + * - a static field, we create a fake clinit method. 1.30 + */ 1.31 private Env<AttrContext> lambdaEnv(JCLambda that, Env<AttrContext> env) { 1.32 Env<AttrContext> lambdaEnv; 1.33 Symbol owner = env.info.scope.owner; 1.34 if (owner.kind == VAR && owner.owner.kind == TYP) { 1.35 //field initializer 1.36 lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dupUnshared())); 1.37 - lambdaEnv.info.scope.owner = 1.38 - new MethodSymbol((owner.flags() & STATIC) | BLOCK, names.empty, null, 1.39 - env.info.scope.owner); 1.40 + ClassSymbol enclClass = owner.enclClass(); 1.41 + /* if the field isn't static, then we can get the first constructor 1.42 + * and use it as the owner of the environment. This is what 1.43 + * LTM code is doing to look for type annotations so we are fine. 1.44 + */ 1.45 + if ((owner.flags() & STATIC) == 0) { 1.46 + for (Symbol s : enclClass.members_field.getElementsByName(names.init)) { 1.47 + lambdaEnv.info.scope.owner = s; 1.48 + break; 1.49 + } 1.50 + } else { 1.51 + /* if the field is static then we need to create a fake clinit 1.52 + * method, this method can later be reused by LTM. 1.53 + */ 1.54 + MethodSymbol clinit = clinits.get(enclClass); 1.55 + if (clinit == null) { 1.56 + Type clinitType = new MethodType(List.<Type>nil(), 1.57 + syms.voidType, List.<Type>nil(), syms.methodClass); 1.58 + clinit = new MethodSymbol(STATIC | SYNTHETIC | PRIVATE, 1.59 + names.clinit, clinitType, enclClass); 1.60 + clinit.params = List.<VarSymbol>nil(); 1.61 + clinits.put(enclClass, clinit); 1.62 + } 1.63 + lambdaEnv.info.scope.owner = clinit; 1.64 + } 1.65 } else { 1.66 lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dup())); 1.67 }