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