/* * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ /* The following jcod code is generated by cd hotspot/jtreg/runtime/cds/appcds cat > test-classes/pkg2/Child.java << EOF package pkg2; import java.util.Optional; import pkg1.BaseWithProtectedMethod; public class Child extends BaseWithProtectedMethod { public void test(Optional opt) { opt.ifPresent(this::protectedMethod); } } EOF mkdir -p tmp javac8 -g:none -d tmp test-classes/pkg1/BaseWithProtectedMethod.java test-classes/pkg2/Child.java java -jar ${ASMTOOL} jdec tmp/pkg2/Child.class >> test-classes/pkg2/Child.jcod rm -f test-classes/pkg2/Child.java */ // NOTES about JDK-8290417 // // The above Java source file (Child.java) must be compiled with JDK 8 or JDK 11 // in order to trigger JDK-8290417 // // Javac in JDK 17 generates a public method for accessing the protected method // in the base class. As a result, InnerClassLambdaMetafactory will not generate // the proxy class in useImplMethodHandle mode. // // public class pkg2.Child extends pkg1.BaseWithProtectedMethod { // public pkg2.Child(); // Code: // 0: aload_0 // 1: invokespecial #1 // Method pkg1/BaseWithProtectedMethod."":()V // 4: return // // public void test(java.util.Optional); // Code: // 0: aload_1 // 1: aload_0 // 2: invokedynamic #7, 0 // InvokeDynamic #0:accept:(Lpkg2/Child;)Ljava/util/function/Consumer; // 7: invokevirtual #11 // Method java/util/Optional.ifPresent:(Ljava/util/function/Consumer;)V // 10: return // // private static void lambda$test$0(pkg2.Child, java.lang.String); // Code: // 0: aload_0 // 1: aload_1 // 2: invokevirtual #17 // Method protectedMethod:(Ljava/lang/String;)V // 5: return // } // // $ java17 -XX:+UnlockDiagnosticVMOptions -XX:+ShowHiddenFrames -cp test-classes LambdaWithUseImplMethodHandleApp // java.lang.Exception: Stack trace // at java.base/java.lang.Thread.dumpStack(Thread.java:1380) // at pkg1.BaseWithProtectedMethod.protectedMethod(BaseWithProtectedMethod.java:29) // at pkg2.Child.lambda$test$0(Child.java:8) // at pkg2.Child$$Lambda/0x0000000800c01000.accept(Unknown Source) // at java.base/java.util.Optional.ifPresent(Optional.java:178) // at pkg2.Child.test(Child.java:8) // at LambdaWithUseImplMethodHandleApp.main(LambdaWithUseImplMethodHandleApp.java:32) class pkg2/Child { 0xCAFEBABE; 0; // minor version 52; // version [] { // Constant Pool ; // first element is empty Method #5 #13; // #1 InvokeDynamic 0s #19; // #2 Method #20 #21; // #3 class #22; // #4 class #23; // #5 Utf8 ""; // #6 Utf8 "()V"; // #7 Utf8 "Code"; // #8 Utf8 "test"; // #9 Utf8 "(Ljava/util/Optional;)V"; // #10 Utf8 "Signature"; // #11 Utf8 "(Ljava/util/Optional;)V"; // #12 NameAndType #6 #7; // #13 Utf8 "BootstrapMethods"; // #14 MethodHandle 6b #24; // #15 MethodType #25; // #16 MethodHandle 5b #26; // #17 MethodType #27; // #18 NameAndType #28 #29; // #19 class #30; // #20 NameAndType #31 #32; // #21 Utf8 "pkg2/Child"; // #22 Utf8 "pkg1/BaseWithProtectedMethod"; // #23 Method #33 #34; // #24 Utf8 "(Ljava/lang/Object;)V"; // #25 Method #5 #35; // #26 Utf8 "(Ljava/lang/String;)V"; // #27 Utf8 "accept"; // #28 Utf8 "(Lpkg2/Child;)Ljava/util/function/Consumer;"; // #29 Utf8 "java/util/Optional"; // #30 Utf8 "ifPresent"; // #31 Utf8 "(Ljava/util/function/Consumer;)V"; // #32 class #36; // #33 NameAndType #37 #41; // #34 NameAndType #42 #27; // #35 Utf8 "java/lang/invoke/LambdaMetafactory"; // #36 Utf8 "metafactory"; // #37 class #44; // #38 Utf8 "Lookup"; // #39 Utf8 "InnerClasses"; // #40 Utf8 "(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;"; // #41 Utf8 "protectedMethod"; // #42 class #45; // #43 Utf8 "java/lang/invoke/MethodHandles$Lookup"; // #44 Utf8 "java/lang/invoke/MethodHandles"; // #45 } // Constant Pool 0x0021; // access #4;// this_cpx #5;// super_cpx [] { // Interfaces } // Interfaces [] { // Fields } // Fields [] { // Methods { // method 0x0001; // access #6; // name_index #7; // descriptor_index [] { // Attributes Attr(#8) { // Code 1; // max_stack 1; // max_locals Bytes[]{ 0x2AB70001B1; } [] { // Traps } // end Traps [] { // Attributes } // Attributes } // end Code } // Attributes } ; { // method 0x0001; // access #9; // name_index #10; // descriptor_index [] { // Attributes Attr(#8) { // Code 2; // max_stack 2; // max_locals Bytes[]{ 0x2B2ABA00020000B6; 0x0003B1; } [] { // Traps } // end Traps [] { // Attributes } // Attributes } // end Code ; Attr(#11) { // Signature #12; } // end Signature } // Attributes } } // Methods [] { // Attributes Attr(#40) { // InnerClasses [] { // classes #38 #43 #39 25; } } // end InnerClasses ; Attr(#14) { // BootstrapMethods [] { // bootstrap_methods { // bootstrap_method #15; // bootstrap_method_ref [] { // bootstrap_arguments #16; #17; #18; } // bootstrap_arguments } // bootstrap_method } } // end BootstrapMethods } // Attributes } // end class pkg2/Child