title: Why does the Java compiler 11 use invokevirtual to call private methods?
body: <p>When compiling the code below with the Java compiler from OpenJDK 8, the call to <code>foo()</code> is done via an <code>invokespecial</code>, but when OpenJDK 11 is used, an <code>invokevirtual</code> is emitted.</p>
  <pre class="lang-java prettyprint-override"><code>public class Invoke {
    public void call() {
      foo();
    }
  
    private void foo() {}
  }
  </code></pre>
  <p>Output of <code>javap -v -p</code> when <code>javac</code> 1.8.0_282 is used:</p>
  <pre><code>  public void call();
      descriptor: ()V
      flags: (0x0001) ACC_PUBLIC
      Code:
        stack=1, locals=1, args_size=1
           0: aload_0
           1: invokespecial #2      // Method foo:()V
           4: return
  </code></pre>
  <p>Output of <code>javap -v -p</code> when <code>javac</code> 11.0.10 is used:</p>
  <pre><code>  public void call();
      descriptor: ()V
      flags: (0x0001) ACC_PUBLIC
      Code:
        stack=1, locals=1, args_size=1
           0: aload_0
           1: invokevirtual #2      // Method foo:()V
           4: return
  
  </code></pre>
  <p>I don't get why <code>invokevirtual</code> is used here since there cannot be an override of <code>foo()</code>.</p>
  <p>After digging a bit it seems that the purpose of <code>invokevirtual</code> on private methods is to allow nested classes to call private methods from the outer class. So I tried the code below:</p>
  <pre class="lang-java prettyprint-override"><code>public class Test{
    public static void main(String[] args) {
      // Build a Derived such that Derived.getValue()
      // somewhat &quot;exists&quot;.
      System.out.println(new Derived().foo());
    }
  
    public static class Base {
  
      public int foo() {
        return getValue() + new Nested().getValueInNested();
      }
  
      private int getValue() {
        return 24;
      }
  
      private class Nested {
  
        public int getValueInNested() {
          // This is getValue() from Base, but would
          // invokevirtual call the version from Derived?
          return getValue();
        }
      }
    }
  
    public static class Derived extends Base {
  
      // Let's redefine getValue() to see if it is picked by the
      // invokevirtual from getValueInNested().
      private int getValue() {
        return 100;
      }
    }
  }
  </code></pre>
  <p>Compiling this code with 11, we can see in the output of <code>javap</code> that <code>invokevirtual</code> is used both in <code>foo()</code> and in <code>getValueInNested()</code>:</p>
  <pre><code>  public int foo();
      descriptor: ()I
      flags: (0x0001) ACC_PUBLIC
      Code:
        stack=4, locals=1, args_size=1
           0: aload_0
  
           // ** HERE **
           1: invokevirtual #2  // Method getValue:()I
           4: new           #3  // class Test$Base$Nested
           7: dup
           8: aload_0
           9: invokespecial #4  // Method Test$Base$Nested.&quot;&lt;init&gt;&quot;:(LTest$Base;)V
          12: invokevirtual #5  // Method Test$Base$Nested.getValueInNested:()I
          15: iadd
          16: ireturn
  </code></pre>
  <pre><code>  public int getValueInNested();
      descriptor: ()I
      flags: (0x0001) ACC_PUBLIC
      Code:
        stack=1, locals=1, args_size=1
           0: aload_0
           1: getfield      #1  // Field this$0:LTest$Base;
  
           // ** HERE **
           4: invokevirtual #3  // Method Test$Base.getValue:()I
           7: ireturn
  </code></pre>
  <p>All of this is a bit confusing and raises some questions:</p>
  <ul>
  <li>Why <code>invokevirtual</code> is used to call private methods? Is there a use case where replacing it by an <code>invokespecial</code> would not be equivalent?</li>
  <li>How does the call to <code>getValue()</code> in <code>Nested.getValueInNested()</code> not pick the method from <code>Derived</code> since it is called via <code>invokevirtual</code>?</li>
  </ul>