enhanced-metadata-spec-discuss Digest, Vol 12, Issue 4

Alex Buckley alex.buckley at oracle.com
Mon Aug 26 13:07:35 PDT 2013


Hi Srikanth,

Many thanks for trying out javac in the JDK 8 builds. Answers below.

On 8/26/2013 11:56 AM, Srikanth S Adayapalam wrote:
> (1) For the following case:
>
> // --
> public class X {
>      void foo() {
>          class Local {
>          }
>      }
> }
> // --
>
> why would javac emit a mandated formal parameter as in
>
>   X$1Local(X);
>     descriptor: (LX;)V
>     flags:
>     Code:
>       stack=2, locals=2, args_size=2
>          0: aload_0
>          1: aload_1
>          2: putfield      #1                  // Field this$0:LX;
>          5: aload_0
>          6: invokespecial #2                  // Method
> java/lang/Object."<init>
> :()V
>          9: return
>       LineNumberTable:
>         line 3: 0
>     MethodParameters:
>       Name                           Flags
>       this$0                         final mandated
>
> // --
>
> I would think this is covered by "The local/
> anonymous class is necessarily emitted by the same compiler as the class
> instance creation
> expression. That compiler can represent the immediately enclosing instance
> how ever
> it wishes. There is no need for the Java programming language to
> implicitly declare a
> parameter in the local/anonymous class's constructor."
>
> and so the parameter need not be mandated ?

I agree. This is a known bug in javac which was identified by unit tests 
on compiler-dev last week. (For those who can read GPL'd lists, it's 
http://mail.openjdk.java.net/pipermail/compiler-dev/2013-August/007190.html.)

> However, per 13.1 we have:
>
> A construct emitted by a Java compiler must be marked as mandated if it
> corresponds to a formal parameter declared implicitly in source code
> (§8.8.9,
> §8.9.2, §15.9.5.1) and per a reading of 15.9.5.1. seems to imply that
> this$0 above should be mandated, since class Local is not
> occurring in a static context.

Not quite. 15.9.5.1 is about constructors of anonymous classes, and 
there is no anonymous class in class X above, so there is nothing in any 
current or future JLS text to say that class Local has an implicitly 
declared formal parameter.

The interesting case is when an anonymous class has a direct superclass 
(the 'S' in 15.9.5.1) which is "special" in some way - private, or local 
in a static context. Per the compiler-dev thread above, I am due to 
update the enhanced metadata spec ASAP to fully enumerate these 
situations in order to completely specify when ctor formal parameters 
are implicitly declared.

> (2) 8.8.9 point 3) reads:
>
>   In a class instance creation expression for an anonymous class, and where
> the anonymous
> class's superclass is inner, §15.9.2 specifies the immediately enclosing
> instance with respect
> to the superclass. Similar to (1), the superclass may have been emitted by
> a compiler which
> is different than the compiler of the class instance creation expression.
> Therefore, there
> must be a standard way for the compiler of the creation expression to pass
> a reference
> (representing the immediately enclosing instance with respect to the
> superclass) to the
> superclass's constructor. Consequently, the Java programming language
> deems that an
> anonymous class's constructor implicitly declares an initial parameter for
> the immediately
> enclosing instance with respect to the superclass.
>
>
> 8b100's behavior is confusing on the following code:
>
> // --
> public class X {
>      void foo() {
>          new Y().new Z() {
>          };
>      }
> }
> class Y {
>      class Z {}
> }
> // --
>
>    final X this$0;
>      descriptor: LX;
>      flags: ACC_FINAL, ACC_SYNTHETIC
>
>    X$1(X, Y);
>      descriptor: (LX;LY;)V
>      flags:
>      Code:
>        stack=3, locals=3, args_size=3
>           0: aload_0
>           1: aload_1
>           2: putfield      #1                  // Field this$0:LX;
>           5: aload_0
>           6: aload_2
>           7: dup
>           8: invokevirtual #2                  // Method
> java/lang/Object.getClas
> s:()Ljava/lang/Class;
>          11: pop
>          12: invokespecial #3                  // Method
> Y$Z."<init>":(LY;)V
>          15: return
>        LineNumberTable:
>          line 3: 0
>      MethodParameters:
>        Name                           Flags
>        this$0                         final mandated
>        x0
>
> Why would the anonymous class's own enclosing instances be mandated
> while "x0" which I presume is the super classes enclosing instance
> be flag less ?

There seem to be two javac (or maybe javap) bugs here:

- The this$0 field and the this$0 formal parameter which supplies it are 
concerned with the immediately enclosing instance of the anonymous 
class's instance. Transmitting this instance to the anonymous class's 
instance is covered by point 2 in 8.8.9. Basically, it's not specified. 
As such, the this$0 field has been ACC_SYNTHETIC since forever, and 
that's a big hint that the this$0 formal parameter should be 
ACC_SYNTHETIC too.

- The x0 formal parameter is implicitly declared by 15.9.5.1 as having 
type Y, because the direct superclass Z of the anonymous class is inner. 
So, x0 should be flagged and displayed as mandated.

Alex


More information about the enhanced-metadata-spec-discuss mailing list