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