Nestmates with invokespecial

Alex Buckley alex.buckley at oracle.com
Fri Apr 5 19:16:00 UTC 2019


// Dropping jls-jvms-spec-comments for the time being.

The code, better formatted:

class X {
   public class Y {
     private void foo() {
       System.out.println("Hello");
     }
   }
   public class Z1 extends Y {
     public class Z2 {
       void bar() {
         Z1.super.foo(); // This call
       }
     }
   }
   public static void main(String[] args) {
     new X().new Z1().new Z2().bar();
   }
}

On 4/4/2019 10:51 PM, Manoj Palat wrote:
> Consider the call Z1.super.foo(); At ecj, for 11+, currently we do not
> create synthetic accessor methods for private nestmate members; instead,
> emit “invokespecial” since both Y and Z2 are nestmates – the relevant
> portion of the byte code is shown below:
>
> void bar();
> descriptor: ()V
> flags: (0x0000)
> Code:
> stack=1, locals=1, args_size=1
> 0: aload_0
> 1: getfield #10 // Field this$1:LX$Z1;
> 4: invokespecial #20 // Method X$Y.foo:()V
> 7: return

To be clear about what you mean by "nestmates": Z2.class has a NestHost 
attribute indicating X, and X.class has a NestMembers attribute 
including Z2.

> Run with any of the latest Java versions (I used the latest Java 12 as
> well); the following error is thrown:
>
> Exception in thread "main" java.lang.VerifyError: Bad invokespecial
> instruction: current class isn't assignable to reference class.
> Exception Details:
> Location:
> X$Z1$Z2.bar()V @4: invokespecial
> Reason:
> Error exists in the bytecode
> Bytecode:
> 0000000: 2ab4 000a b700 14b1
>
> at X.main(_X.java:14_)
>
> Is this a problem in verification of invokespecial, where the nestmates
> are not considered? Or are we supposed to go via synthetic emulation for
> qualified super class private methods even if they are nestmates?
>
> Note: at JVMS 11 - 4.9.2, under invokespecial, I don’t see the nestmates
> referred to, although the corresponding bug
> _https://bugs.openjdk.java.net/browse/JDK-8177020_mentions that the
> “proposed changes” include the addition of “With nestmates it may also
> name a method of a nestmate's class. “ to section 4.9.2.**Any reason(s)
> for the omission of this condition?

In JDK-8177020, there are notable changes between the April 2017 spec 
(private-access.html) and the May 2018 spec (nestmates.html). In line 
with the bug's Description, the 2017 spec had a lot to say about 
invokespecial. However, the 2018 spec took a different tack for privat 
methods. In nestmates.html, see the commentary on a change in 3.7:

"Because private methods may now be invoked from a nestmate class, it is 
no longer recommended to compile their invocation to invokespecial. 
(invokespecial may only be used for methods declared in the current 
class or a superclass.) A standard usage of invokevirtual or 
invokeinterface works just fine instead, with no special discussion 
necessary."

Accordingly, JVMS 11 didn't change invokespecial's verification; the 
relevant high-level rule in 4.9.2 is still "If an invokespecial 
instruction names a method which is not an instance initialization 
method, then the target reference on the operand stack must be a class 
instance whose type is assignment compatible with the current class."

Frankly, JEP 181 presented a lot of low-level rule changes to 
invoke{special,virtual,interface} but didn't do a great job of 
presenting a single high-level description of intent. For example, 
nestmates.html flags the major change of "Modifying the behavior of 
invokeinterface to support invocation of private methods.", but that 
simply raises a hundred questions, which could be addressed by (say) a 
matrix of bytecodes and kinds-of-method. I hope Dan can share some 
thoughts, on this list, of the full invoke* story intended by JEP 181.

Alex


More information about the jls-jvms-spec-comments mailing list