Different behaviors of Ref_InvokeSpecial

Mandy Chung mandy.chung at oracle.com
Mon Oct 4 20:59:39 UTC 2021


(valhalla-dev is a proper mailing list to discuss that.  I bcc jdk-dev).

Hi Zeker,

Which version of javac are you using?  I compiled it with JDK 8u331 and 
can't reproduce the problem.

$ jdk1.8.0_311.jdk/bin/java -version
java version "1.8.0_311-ea"
Java(TM) SE Runtime Environment (build 1.8.0_311-ea-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.311-b01, mixed mode)

$ jdk1.8.0_311.jdk/bin/javac -version
javac 1.8.0_311-ea

$ jdk1.8.0_311.jdk/bin/javac ExampleClass.java
$ jdk1.8.0_311.jdk/bin/java ExampleClass
123

$ jdk-15.jdk/bin/java -version
java version "15" 2020-09-15
Java(TM) SE Runtime Environment (build 15+36-1562)
Java HotSpot(TM) 64-Bit Server VM (build 15+36-1562, mixed mode, sharing)

$ jdk-15.jdk/bin/java ExampleClass
123


Note that the JVMS change related to invokespecial is part of JEP 181 
Nest-based Access Control.  The hidden classes generated by 
LambdaMetaFactory is a nestmate of the target class and so the bytecode 
generated was fixed in JEP 371 to use invokevirtual or invokeinterface 
per JVMS.

The bootstrap method javac generated is REF_invokeSpecial in your 
ExampleClass.  LMF does special handle it for compatibility for existing 
code to behave as in older releases.

BootstrapMethods:
   0: #34 REF_invokeStatic 
java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
     Method arguments:
       #35 ()Ljava/lang/Object;
       #36 REF_invokeSpecial ExampleClass.testPrivate:()Ljava/lang/String;
       #37 ()Ljava/lang/String;


I don't see any issue from ExampleClass.

Mandy

On 10/4/21 2:50 AM, Zeker Zhayard wrote:
> Hi,
> JEP 371 describes that to invoke private nestmate instance methods from
> code in a hidden class, use invokevirtual or invokeinterface instead of
> invokespecial and generated bytecode that uses invokespecial to invoke a
> private nestmate instance method will fail verification. invokespecial
> should only be used to invoke private nestmate constructors.
> However, consider the following use case:
>
> import java.util.function.Supplier;
>
> public class ExampleClass {
>      public static void main(String[] args) {
>          System.out.println(new SubClass().test());
>      }
>
>      public String test() {
>          Supplier<String> supplier = this::testPrivate;
>          return supplier.get();
>      }
>
>      private String testPrivate() {
>          return "123";
>      }
>
>      public static class SubClass extends ExampleClass {
>          public String testPrivate() {
>              return "456";
>          }
>      }
> }
>
> 1. Compile it with Java 8
> 2. Modify the access of ExampleClass#testPrivate to protected in bytecode
> 3. Running in Java 15+ will get "456" rather than "123" in Java 8~14



More information about the jdk-dev mailing list