1 /*
  2  * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 import java.lang.reflect.Method;
 25 import jdk.test.lib.Asserts;
 26 import jdk.test.whitebox.WhiteBox;
 27 
 28 import jdk.internal.vm.annotation.ImplicitlyConstructible;
 29 import jdk.internal.vm.annotation.LooselyConsistentValue;
 30 import jdk.internal.vm.annotation.NullRestricted;
 31 
 32 /*
 33  * @test
 34  * @key randomness
 35  * @bug 8280006
 36  * @summary Test that field flattening works as expected if value classes of
 37  *          holder and field were loaded by different class loaders (bootstrap + app).
 38  * @library /test/lib /
 39  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
 40  * @enablePreview
 41  * @modules java.base/jdk.internal.value
 42  *          java.base/jdk.internal.vm.annotation
 43  * @compile ValueOnBootclasspath.java InstallBootstrapClasses.java TestBootClassloader.java
 44  * @build jdk.test.whitebox.WhiteBox
 45  * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
 46  * @run main/othervm InstallBootstrapClasses
 47  * @run main/othervm -Xbootclasspath/a:boot -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
 48  *                   -Xbatch -XX:-TieredCompilation -XX:CompileCommand=compileonly,TestBootClassloader::test*
 49  *                   -XX:CompileCommand=inline,*::get* TestBootClassloader
 50  */
 51 
 52 public class TestBootClassloader {
 53     private static final WhiteBox WB = WhiteBox.getWhiteBox();
 54     private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
 55 
 56     @ImplicitlyConstructible
 57     @LooselyConsistentValue
 58     static value class Wrapper1 {
 59         @NullRestricted
 60         ValueOnBootclasspath val; // Type will be loaded by boot classloader
 61 
 62         public Wrapper1(ValueOnBootclasspath val) {
 63             this.val = val;
 64         }
 65 
 66         Object get() {
 67             return val.get();
 68         }
 69     }
 70 
 71     @ImplicitlyConstructible
 72     @LooselyConsistentValue
 73     static value class Wrapper2 {
 74         @NullRestricted
 75         Wrapper1 val;
 76 
 77         public Wrapper2(Wrapper1 val) {
 78             this.val = val;
 79         }
 80 
 81         Object get() {
 82             return val.get();
 83         }
 84     }
 85 
 86     static Object test1(Wrapper1 w) {
 87         return w.get();
 88     }
 89 
 90     static Object test2(Wrapper2 w) {
 91         return w.get();
 92     }
 93 
 94     public static void main(String[] args) throws Exception {
 95         Wrapper1 wrapper1 = new Wrapper1(new ValueOnBootclasspath());
 96         Wrapper2 wrapper2 = new Wrapper2(wrapper1);
 97         for (int i = 0; i < 50_000; ++i) {
 98             test1(wrapper1);
 99             test2(wrapper2);
100         }
101         Method method = TestBootClassloader.class.getDeclaredMethod("test1", Wrapper1.class);
102         Asserts.assertTrue(WB.isMethodCompilable(method, COMP_LEVEL_FULL_OPTIMIZATION, false), "Test1 method not compilable");
103         Asserts.assertTrue(WB.isMethodCompiled(method), "Test1 method not compiled");
104 
105         method = TestBootClassloader.class.getDeclaredMethod("test2", Wrapper2.class);
106         Asserts.assertTrue(WB.isMethodCompilable(method, COMP_LEVEL_FULL_OPTIMIZATION, false), "Test2 method not compilable");
107         Asserts.assertTrue(WB.isMethodCompiled(method), "Test2 method not compiled");
108     }
109 }