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