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