Nestmates with invokespecial

Dan Smith daniel.smith at oracle.com
Mon Apr 8 23:44:47 UTC 2019


I assume that, in general, you've switched to 'invokevirtual' for private methods, per the discussion in the JEP and the spec document.

What's tricky about this example is that you don't want a virtual invocation—you need the 'super' invocation mode. So 'invokevirtual' is no good.

And what you need to note is that JEP 181 didn't give any new capabilities to invokespecial (aside from indirect benefits from new accessibility rules)—it can only invoke i) constructors and ii) methods of the caller/its supers. Doesn't matter whether the referenced method is accessible or not.

So, when it comes to 'super' invocations of the methods of an outer class's supertypes, you'll need to continue generating bridges (whether the outer's super is in the same nest or not).

---

To the request to unpack some of the changes:

> On Apr 5, 2019, at 1:16 PM, Alex Buckley <alex.buckley at oracle.com> wrote:
> 
> 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.

(Meta-note: yes, the artifacts we've produced are somewhat hard to follow. We should do a better job of laying out a high-level view of the changes in the JEP and/or the spec document header.)

I can try to offer some clarity. The header of nestmates.html describes two changes, and that is a good place to start:

1) A private member in another class may now be accessible, by virtue of the NestHost and NestMembers attributes of the caller/callee.

This means that some bytecode that would have previously resulted in an IAE due to an inaccessible private member now succeeds. The description is not precise about referenced vs. declaring classes; the key definitions are in 5.4.4.

The trick about the invokespecial instruction in question:

>  invokespecial #20 // Method X$Y.foo:()V

is that it was formerly illegal for *two* reasons:
- The referenced method is private and not accessible to Z2
- The referenced method is not declared in the caller or its supers.

Now it's illegal for just one reason. But still illegal. (Why didn't we "fix" that? Because fixing it properly is hard and complex, and we didn't feel doing so was justified.)

These accessibility changes affect all instructions that rely on member references *except for invokeinterface* (discussed next), including invokevirtual, invokestatic, and invokespecial.

2) The invokeinterface instruction may be used to invoke private methods.

A former rule explicitly required that the method referenced by invokeinterface be public. We relaxed that, allowing it to be private as well, thus able to take advantage of the changes in (1) (if the private method turns out to be accessible).

Those are really the only meaningful changes (aside from some cornery changes called out in the discussion boxes). In particular, while there are refactorings to improve the presentation of the invoke* instructions, there are no meaningful changes to them, except as discussed above.



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