1 /*
  2  * Copyright (c) 2019, 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 package runtime.valhalla.inlinetypes;
 24 
 25 import jdk.test.lib.Asserts;
 26 import jdk.internal.vm.annotation.LooselyConsistentValue;
 27 import jdk.internal.vm.annotation.NullRestricted;
 28 import jdk.internal.vm.annotation.Strict;
 29 
 30 
 31 /*
 32  * @test
 33  * @summary Test circularity in static fields
 34  * @library /test/lib
 35  * @modules java.base/jdk.internal.vm.annotation
 36  * @enablePreview
 37  * @compile StaticFieldsTest.java
 38  * @run main/othervm runtime.valhalla.inlinetypes.StaticFieldsTest
 39  */
 40 
 41 public class StaticFieldsTest {
 42 
 43 
 44     // ClassA and ClassB have a simple cycle in their static fields, but they should
 45     // be able to load and initialize themselves successfully. Access to these
 46     // static fields after their initialization should return the default value.
 47     @LooselyConsistentValue
 48     static value class ClassA {
 49         @Strict
 50         @NullRestricted
 51         static ClassB b = new ClassB();
 52         public int i;
 53 
 54         public ClassA() {
 55             i = 3;
 56         }
 57     }
 58 
 59     @LooselyConsistentValue
 60     static value class ClassB {
 61         @Strict
 62         @NullRestricted
 63         static ClassA a = new ClassA();
 64         public int i;
 65 
 66         public ClassB() {
 67             i = 700;
 68         }
 69     }
 70 
 71     // ClassC has a reference to itself in its static field, but it should be able
 72     // to initialize itself successfully. Access to this static field after initialization
 73     // should return the default value.
 74     @LooselyConsistentValue
 75     static value class ClassC {
 76         @Strict
 77         @NullRestricted
 78         static ClassC c = new ClassC();
 79         int i;
 80 
 81         public ClassC() {
 82             i = 42;
 83         }
 84     }
 85 
 86 
 87     // ClassD and ClassE have circular references in their static fields, and they
 88     // read these static fields during their initialization, the value read from
 89     // these fields should be the default value. Both classes should initialize
 90     // successfully.
 91     @LooselyConsistentValue
 92     static value class ClassD {
 93         @Strict
 94         @NullRestricted
 95         static ClassE e = new ClassE();
 96         int i;
 97 
 98         static {
 99             Asserts.assertEquals(e.i, 42, "Static field e.i incorrect");
100         }
101 
102         public ClassD() {
103             i = 42;
104         }
105     }
106 
107     @LooselyConsistentValue
108     static value class ClassE {
109         @Strict
110         @NullRestricted
111         static ClassD d = new ClassD();
112         int i;
113 
114         static {
115             Asserts.assertEquals(d.i, 42, "Static field d.i incorrect");
116         }
117 
118         public ClassE() {
119             i = 42;
120         }
121     }
122 
123     // ClassF and ClassG have circular references in their static fields, and they
124     // create new instances of each other type to initialize these static fields
125     // during their initialization. Both classes should initialize successfully.
126     @LooselyConsistentValue
127     static value class ClassF {
128         @Strict
129         @NullRestricted
130         static ClassG g = new ClassG();
131         int i;
132 
133         static {
134             g = new ClassG();
135             Asserts.assertEquals(g.i, 64, "Static field ClassF.g.i incorrect");
136         }
137 
138         ClassF() {
139             i = 314;
140         }
141     }
142 
143     @LooselyConsistentValue
144     static value class ClassG {
145         @Strict
146         @NullRestricted
147         static ClassF f = new ClassF();
148         int i;
149 
150         static {
151             f = new ClassF();
152             Asserts.assertEquals(f.i, 314, "Static field ClassG.f.i incorrect");
153         }
154 
155         ClassG() {
156             i = 64;
157         }
158     }
159 
160     public static void main(String[] args) {
161         Asserts.assertEquals(ClassA.b.i, 700, "Static field ClassA.b.i incorrect");
162         Asserts.assertEquals(ClassB.a.i, 3, "Static field Classb.a.i incorrect");
163         Asserts.assertEquals(ClassC.c.i, 42, "Static field ClassC.c.i incorrect");
164         new ClassD();
165         new ClassF();
166     }
167 }