Why does the Java compiler 11 use invokevirtual to call private methods?

This was done as part of https://openjdk.java.net/jeps/181: Nest-Based Access Control, so that the JVM can allow access to private methods from nested classes.

Before that change, the compiler would have to generate a package-protected synthetic method in the Base class, which the nested class invokes. That synthetic method would in turn call the private method in the Base class. The feature in Java 11 enhances the JVM to allow that without the compiler having to generate a synthetic method.

Concerning the point on whether invokevirtual will call the method in the Derived class, the answer is no. The private method is still not subject to method selection of the runtime class (this has never changed):

During execution of an invokeinterface or invokevirtual instruction, a method is selected with respect to (i) the run-time type of the object on the stack, and (ii) a method that was previously resolved by the instruction. The rules to select a method with respect to a class or interface C and a method mR are as follows:

  1. If mR is marked ACC_PRIVATE, then it is the selected method.

EDIT:

Based on the comment “Would it be valid to still use invokespecial if the private method is called from the method owner class and use invokevirtual if it is called from a nested class?”

As Holger mentioned, yes it is valid, but based on the JEP, I’m guessing a decision was made to switch to invokevirtual for simplicity (I cannot confirm this though, it’s just a guess):

With the change to the access rules, and with suitable adjustments to byte code rules, we can allow simplified rules for generating invocation bytecodes:

  • invokespecial for private nestmate constructors,
  • invokevirtual for private non-interface, nestmate instance methods,
  • invokeinterface for private interface, nestmate instance methods; and
  • invokestatic for private nestmate, static methods

Another interesting note from JDK-8197445 : Implementation of JEP 181: Nest-Based Access Control:

Traditionally, invokespecial is used to invoke private members, though invokevirtual also has this capability. Rather than perturb the complex rules about supertypes enforced by invokespecial, we require invocations of private methods in a different class to use invokevirtual.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)