Review request for JDK-8020745: Suspicious MethodParameters attribute generated for local classes capturing local variables
Alex Buckley
alex.buckley at oracle.com
Wed Aug 28 19:26:55 PDT 2013
As I suspected, there is a hole in the JLS: the immediately enclosing
instance of an inner member class is determined by 15.9.2 but is not
specified as being passed to the constructor of the inner member class
by 15.9.3.
The JLS _must_ specify that it is passed, for the reason given in
8misc.pdf: the member class may have been emitted by a compiler which is
different than the compiler of the CICE, so there must be a standard way
for the compiler of the CICE to transmit the immediately enclosing
instance to the member class's constructor.
15.9.3 only remembers to pass an extra value to the constructor of an
anonymous class whose superclass is inner; the value in that case is the
immediately enclosing instance with respect to the superclass. (Assuming
the superclass is not local in a static context, in which case there is
no value to pass.)
I have filed JDK-8023949 to change the JLS to reflect what Java
compilers must have been doing since 1997.
On 8/22/2013 4:30 PM, Eric McCorkle wrote:
> On 08/22/13 14:35, Alex Buckley wrote:
>
>> Now the bad news:
>>
>> - The makeLocal case is incorrect. Since LocalTester is local, the
>> only code that can instantiate it is in the body of the makeLocal
>> method. This means the immediately enclosing instance of
>> LocalTester can be transmitted to LocalTester's ctor in a
>> proprietary manner; the JLS does not specify it. Hence, this$1
>> should be SYNTHETIC, not MANDATED.
>
> That would be a problem in javac's gen.
OK.
>> - The makeAnonExtendsLocal case is tricky. Please recognize that
>> the constructor of the abstract class LocalTester is not the same
>> thing as the constructor of the anonymous class whose superclass is
>> LocalTester. names() et al in the abstract class LocalTester are
>> necessarily identical to those in the class LocalTester in
>> makeLocal; they should be removed from makeAnonExtendsLocal. Then,
>> please add names() et al to the body of the anonymous class, akin
>> to the anonymous class declared in makeAnonExtendsInner. What
>> values are expected by the new names()? Good question. The
>> anonymous class in makeAnonExtendsLocal has a superclass
>> (LocalTester) which is inner but also local, so the spec is not
>> clear how to transmit the immediately enclosing instance of the
>> anonymous class with respect to the superclass. Again, I intend to
>> clarify the spec ASAP.
>
> Let me know when you do, and I'll file an appropriate request.
In makeAnonExtendsLocal, you have "return new LocalTester(2) {...}".
This anonymous class has a superclass which is a local class not in a
static context. JLS 15.9.3 always said to pass the immediately enclosing
instance of the new object with respect to LocalTester to the anonymous
class's constructor. Similarly, JLS 15.9.5.1 always said that the
anonymous class's constructor has a first formal parameter of type
Encloser (the class enclosing LocalTester). So the this$1 parameter in
the constructor should be MANDATED.
This case is interesting because the mandated first formal parameter
doesn't really need to be specified; see the sidebar in JDK-8023949. But
the JLS has been clear about this case since 1997, and it ties back to
15.9.2's determination of immediately enclosing instance with respect to
the superclass. So it's not changeable now.
Alex
More information about the compiler-dev
mailing list