Review request: update javac to properly output mandated parameters in MethodParameters attributes

John Rose john.r.rose at oracle.com
Wed Feb 13 15:01:20 PST 2013


On Feb 13, 2013, at 12:44 PM, Alex Buckley <alex.buckley at oracle.com> wrote:

> On 2/12/2013 10:22 PM, John Rose wrote:
>> 
>> It's always used ACC_SYNTHETIC but that doesn't mean that ACC_MANDATED
>> would be better for some bits of the puzzle.
> 
> It would be pleasant to treat private and non-private ctors of member classes the same, but as a practical matter, I don't know that all Java compilers even use a ctor parameter to pass immediately-enclosing-instance for a private member class. For a non-private member class, I am happier to assume that all Java compilers followed javac and that new JLS text is relatively harmless.
> 
> I added a note to the new 8.8.9 that the mandating of ctor parameters for member classes v. local/anonymous classes mirrors the mandating of predictable v. non-predictable binary names in 13.1 - thanks for reminding me of that link.
> 
>> P.S. Do we still mandate names of certain inner class fields, such as
>> 'this$NNN'?  The original motivation for this was to allow debuggers a
>> somewhat easier time presenting compiler-generated data structures.
> 
> The JLS has never done this, so I don't know who would be mandating it.

It was me.  I am emphasizing the past tense "was".  And the naming of synthetics was "strongly encouraged though not required".  The penalty for varying from the naming rules was, mainly, possible loss of integration with tools.

Here *was* the document:

http://web.archive.org/web/20000830111107/http://java.sun.com/products/jdk/1.1/docs/guide/innerclasses/spec/innerclasses.doc10.html

This specification, such as it was, has been superseded by the JLS.  In its time it caused third-party java compilers to exhibit a certain regularity of behavior with respect to inner classes.  I have no clear idea where the bits in it went or which were modified or dropped by the various editors of the JLS.  Here are some of the old bits relevant to the present discussion, FTR:

> Java 1.1 compilers are strongly encouraged, though not required, to use the following naming conventions when implementing inner classes. Compilers may not use synthetic names of the forms defined here for any other purposes.
> 
> A synthetic field pointing to the outermost enclosing instance is named this$0. The next-outermost enclosing instance is this$1, and so forth. (At most one such field is necessary in any given inner class.) A synthetic field containing a copy of a constant v is named val$v. These fields are final.
> 
> All these synthetic fields are initialized by constructor parameters, which have the same names as the fields they initialize. If one of the parameters is the innermost enclosing instance, it is the first. All such constructor parameters are deemed to be synthetic. If the compiler determines that the synthetic field's value is used only in the code of the constructor, it may omit the field itself, and use only the parameter to implement variable references.
> 
> A non-private final synthetic method which grants access to a private member or constructor has a name of the form access$N, where N is a decimal numeral. The organization of such access protocols is unspecified.
> 
> Debuggers and similar tools which are 1.1 compatible must recognize these naming conventions, and organize variable displays and symbol tables accordingly. Note that tools may need to parse these names. Compilers are strongly encouraged to use these conventions, at least by default.

And from another page, some non-mandated guidance:

http://web.archive.org/web/20000830111024/http://java.sun.com/products/jdk/1.1/docs/guide/innerclasses/spec/innerclasses.doc2.html
> Inner class code is typically defined relative to some enclosing class instance, so the inner class instance needs to be able to determine the enclosing instance.
> The JavaSoft Java 1.1 compiler arranges this by adding an extra private instance variable which links the inner class to the enclosing class. This variable is initialized from an extra argument passed to the inner class constructor. That argument, in turn, is determined by the expression which creates the inner class instance; by default it is the object doing the creation.
> ...each inner class constructor receives the enclosing instance in a prepended argument.


The document says nothing about the interaction between inner class binary APIs and reflection.  I guess this is because both features were new in 1.1 and we hadn't figured out yet how they would need to interact.  I forget exactly when we decided to mandate a leading this$N parameter on all inner constructors (at least of members), but I think (as I said earlier) it is a friendly assurance to users of the Core Reflection API.

— John

P.S. <smug>That document also points out clearly why captured locals must be 'final', and has an example of the "dotimes bug".  Too bad C# got that wrong and had to back out.</smug>


More information about the compiler-dev mailing list