1 /*
  2  * Copyright (c) 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 /*
 25  * @test PreloadCircularityTest
 26  * @modules java.base/jdk.internal.vm.annotation
 27  *          java.base/jdk.internal.value
 28  * @library /test/lib
 29  * @enablePreview
 30  * @compile PreloadCircularityTest.java
 31  * @run main/othervm PreloadCircularityTest
 32  */
 33 
 34  import java.lang.reflect.Method;
 35  import java.util.ArrayList;
 36  import java.util.Collections;
 37  import java.util.List;
 38 
 39 import javax.management.relation.RelationServiceNotRegisteredException;
 40 
 41  import jdk.internal.value.ValueClass;
 42  import jdk.internal.vm.annotation.ImplicitlyConstructible;
 43  import jdk.internal.vm.annotation.LooselyConsistentValue;
 44  import jdk.internal.vm.annotation.NullRestricted;
 45 
 46 import jdk.test.lib.Asserts;
 47 import jdk.test.lib.Utils;
 48 import jdk.test.lib.process.OutputAnalyzer;
 49 import jdk.test.lib.process.ProcessTools;
 50 
 51 public class PreloadCircularityTest {
 52 
 53     // Testing preload due to non-static fields
 54 
 55     static value class Class0a {
 56         @NullRestricted
 57         Class0b vb = new Class0b();
 58     }
 59 
 60     @ImplicitlyConstructible
 61     static value class Class0b {
 62         @NullRestricted
 63         Class0c vc = new Class0c();
 64     }
 65 
 66     @ImplicitlyConstructible
 67     static value class Class0c {
 68         int i = 0;
 69     }
 70 
 71     void test_0() throws Exception {
 72         OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class0a");
 73         out.shouldHaveExitValue(0);
 74         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class0b during loading of class PreloadCircularityTest$Class0a. Cause: a null-free non-static field is declared with this type");
 75         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class0c during loading of class PreloadCircularityTest$Class0b. Cause: a null-free non-static field is declared with this type");
 76         out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class0c during loading of class PreloadCircularityTest$Class0b (cause: null-free non-static field) succeeded");
 77         out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class0b during loading of class PreloadCircularityTest$Class0a (cause: null-free non-static field) succeeded");
 78         out.shouldNotContain("(cause: null-free non-static field) failed");
 79     }
 80 
 81     static value class Class1a {
 82         @NullRestricted
 83         Class1b vb = new Class1b();
 84     }
 85 
 86     @ImplicitlyConstructible
 87     static value class Class1b {
 88         Class1c vc = new Class1c();
 89     }
 90 
 91     static value class Class1c {
 92         int i = 0;
 93     }
 94 
 95     void test_1() throws Exception {
 96         OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class1a");
 97         out.shouldHaveExitValue(0);
 98         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class1b during loading of class PreloadCircularityTest$Class1a. Cause: a null-free non-static field is declared with this type");
 99         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class1c during loading of class PreloadCircularityTest$Class1b. Cause: field type in Preload attribute");
100         out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class1c during loading of class PreloadCircularityTest$Class1b (cause: field type in Preload attribute) succeeded");
101         out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class1b during loading of class PreloadCircularityTest$Class1a (cause: null-free non-static field) succeeded");
102     }
103 
104     static value class Class2a {
105         @NullRestricted
106         Class2b vb = new Class2b();
107     }
108 
109     @ImplicitlyConstructible
110     static value class Class2b {
111         @NullRestricted
112         Class2c vc = new Class2c();
113     }
114 
115     @ImplicitlyConstructible
116     static value class Class2c {
117         @NullRestricted
118         Class2b vb = new Class2b();
119     }
120 
121     void test_2() throws Exception {
122         OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class2a");
123         out.shouldHaveExitValue(1);
124         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class2b during loading of class PreloadCircularityTest$Class2a. Cause: a null-free non-static field is declared with this type");
125         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class2c during loading of class PreloadCircularityTest$Class2b. Cause: a null-free non-static field is declared with this type");
126         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class2b during loading of class PreloadCircularityTest$Class2c. Cause: a null-free non-static field is declared with this type");
127         out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class2b during loading of class PreloadCircularityTest$Class2c (cause: null-free non-static field) failed: java/lang/ClassCircularityError");
128         out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class2c during loading of class PreloadCircularityTest$Class2b (cause: null-free non-static field) failed: java/lang/ClassCircularityError");
129         out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class2b during loading of class PreloadCircularityTest$Class2a (cause: null-free non-static field) failed: java/lang/ClassCircularityError");
130     }
131 
132     static value class Class3a {
133         @NullRestricted
134         Class3b vb = new Class3b();
135     }
136 
137     @ImplicitlyConstructible
138     static value class Class3b {
139         @NullRestricted
140         Class3c vc = new Class3c();
141     }
142 
143     @ImplicitlyConstructible
144     static value class Class3c {
145         Class3b vb = new Class3b();
146     }
147 
148     void test_3() throws Exception {
149         OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class3a");
150         out.shouldHaveExitValue(0);
151         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class3b during loading of class PreloadCircularityTest$Class3a. Cause: a null-free non-static field is declared with this type");
152         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class3c during loading of class PreloadCircularityTest$Class3b. Cause: a null-free non-static field is declared with this type");
153         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class3b during loading of class PreloadCircularityTest$Class3c. Cause: field type in Preload attribute");
154         out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class3b during loading of class PreloadCircularityTest$Class3c (cause: field type in Preload attribute) failed : java/lang/ClassCircularityError");
155         out.shouldContain("[info   ][class,preload] Preloading of class PreloadCircularityTest$Class3c during loading of class PreloadCircularityTest$Class3b (cause: null-free non-static field) succeeded");
156         out.shouldContain("[info   ][class,preload] Preloading of class PreloadCircularityTest$Class3b during loading of class PreloadCircularityTest$Class3a (cause: null-free non-static field) succeeded");
157     }
158 
159     static value class Class4a {
160         @NullRestricted
161         Class4b vb = new Class4b();
162     }
163 
164     @ImplicitlyConstructible
165     static value class Class4b {
166         @NullRestricted
167         Class4a vc = new Class4a();
168     }
169 
170     void test_4() throws Exception {
171         OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class4a");
172         out.shouldHaveExitValue(1);
173         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class4b during loading of class PreloadCircularityTest$Class4a. Cause: a null-free non-static field is declared with this type");
174         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class4a during loading of class PreloadCircularityTest$Class4b. Cause: a null-free non-static field is declared with this type");
175         out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class4a during loading of class PreloadCircularityTest$Class4b (cause: null-free non-static field) failed: java/lang/ClassCircularityError");
176         out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class4b during loading of class PreloadCircularityTest$Class4a (cause: null-free non-static field) failed: java/lang/ClassCircularityError");
177     }
178 
179     static value class Class5a {
180         Class5b vb = new Class5b();
181 
182         @NullRestricted
183         Class5c vc = new Class5c();
184     }
185 
186     static value class Class5b {
187         @NullRestricted
188         Class5d vd = new Class5d();
189     }
190 
191     @ImplicitlyConstructible
192     static value class Class5c {
193         Class5b vb = new Class5b();
194     }
195 
196     static value class Class5d {
197         @NullRestricted
198         Class5b vb = new Class5b();
199     }
200 
201     void test_5() throws Exception {
202         OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class5a");
203         out.shouldHaveExitValue(0);
204         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class5b during loading of class PreloadCircularityTest$Class5a. Cause: field type in Preload attribute");
205         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class5d during loading of class PreloadCircularityTest$Class5b. Cause: a null-free non-static field is declared with this type");
206         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class5b during loading of class PreloadCircularityTest$Class5d. Cause: a null-free non-static field is declared with this type");
207         out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class5b during loading of class PreloadCircularityTest$Class5d (cause: null-free non-static field) failed: java/lang/ClassCircularityError");
208         out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class5d during loading of class PreloadCircularityTest$Class5b (cause: null-free non-static field) failed: java/lang/ClassCircularityError");
209         out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class5b during loading of class PreloadCircularityTest$Class5a (cause: field type in Preload attribute) failed : java/lang/ClassCircularityError");
210         out.shouldContain("[info   ][class,preload] Preloading class PreloadCircularityTest$Class5c during loading of class PreloadCircularityTest$Class5a. Cause: a null-free non-static field is declared with this type");
211         out.shouldContain("[info   ][class,preload] Preloading class PreloadCircularityTest$Class5b during loading of class PreloadCircularityTest$Class5c. Cause: field type in Preload attribute");
212         out.shouldContain("[info   ][class,preload] Preloading class PreloadCircularityTest$Class5d during loading of class PreloadCircularityTest$Class5b. Cause: a null-free non-static field is declared with this type");
213         out.shouldContain("[info   ][class,preload] Preloading class PreloadCircularityTest$Class5b during loading of class PreloadCircularityTest$Class5d. Cause: a null-free non-static field is declared with this type");
214         out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class5b during loading of class PreloadCircularityTest$Class5d (cause: null-free non-static field) failed: java/lang/ClassCircularityError");
215         out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class5d during loading of class PreloadCircularityTest$Class5b (cause: null-free non-static field) failed: java/lang/ClassCircularityError");
216         out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class5b during loading of class PreloadCircularityTest$Class5c (cause: field type in Preload attribute) failed : java/lang/ClassCircularityError");
217         out.shouldContain("[info   ][class,preload] Preloading of class PreloadCircularityTest$Class5c during loading of class PreloadCircularityTest$Class5a (cause: null-free non-static field) succeeded");
218     }
219 
220     static value class Class6a {
221         @NullRestricted
222         Class6b vb = new Class6b();
223     }
224 
225     @ImplicitlyConstructible
226     static value class Class6b {
227         Class6c vc = new Class6c();
228 
229         @NullRestricted
230         Class6d vd = new Class6d();
231     }
232 
233     static value class Class6c {
234         int i = 0;
235     }
236 
237     @ImplicitlyConstructible
238     static value class Class6d {
239         @NullRestricted
240         Class6b vb = new Class6b();
241     }
242 
243     void test_6() throws Exception {
244         OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class6a");
245         out.shouldHaveExitValue(1);
246         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class6b during loading of class PreloadCircularityTest$Class6a. Cause: a null-free non-static field is declared with this type");
247         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class6c during loading of class PreloadCircularityTest$Class6b. Cause: field type in Preload attribute");
248         out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class6c during loading of class PreloadCircularityTest$Class6b (cause: field type in Preload attribute) succeeded");
249         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class6d during loading of class PreloadCircularityTest$Class6b. Cause: a null-free non-static field is declared with this type");
250         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class6b during loading of class PreloadCircularityTest$Class6d. Cause: a null-free non-static field is declared with this type");
251         out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class6b during loading of class PreloadCircularityTest$Class6d (cause: null-free non-static field) failed: java/lang/ClassCircularityError");
252         out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class6d during loading of class PreloadCircularityTest$Class6b (cause: null-free non-static field) failed: java/lang/ClassCircularityError");
253         out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class6b during loading of class PreloadCircularityTest$Class6a (cause: null-free non-static field) failed: java/lang/ClassCircularityError");
254     }
255 
256     @ImplicitlyConstructible
257     static value class Class7a {
258         @NullRestricted
259         Class7a va = new Class7a();
260     }
261 
262     void test_7() throws Exception {
263         OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class7a");
264         out.shouldHaveExitValue(1);
265         out.shouldNotContain("[info][class,preload] Preloading class PreloadCircularityTest$Class7a during loading of class PreloadCircularityTest$Class7a. Cause: a null-free non-static field is declared with this type");
266     }
267 
268     static value class Class8a {
269         Class8a va = new Class8a();
270     }
271 
272     void test_8() throws Exception {
273         OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class8a");
274         out.shouldHaveExitValue(0);
275         out.shouldNotContain("[info][class,preload] Preloading class PreloadCircularityTest$Class8a during loading of class PreloadCircularityTest$Class8a. Cause: a null-free non-static field is declared with this type");
276     }
277 
278     static value class Class9a {
279         @NullRestricted
280         Class9b vb = new Class9b();
281     }
282 
283     static class Class9b { }
284 
285     void test_9() throws Exception {
286         OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class9a");
287         out.shouldHaveExitValue(1);
288         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class9b during loading of class PreloadCircularityTest$Class9a. Cause: a null-free non-static field is declared with this type");
289         out.shouldContain("java.lang.IncompatibleClassChangeError: Class PreloadCircularityTest$Class9a expects class PreloadCircularityTest$Class9b to be a value class, but it is an identity class");
290     }
291 
292     static value class Class10a {
293         @NullRestricted
294         Class10b vb = new Class10b();
295     }
296 
297     static value class Class10b { }
298 
299     void test_10() throws Exception {
300         OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class10a");
301         out.shouldHaveExitValue(1);
302         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class10b during loading of class PreloadCircularityTest$Class10a. Cause: a null-free non-static field is declared with this type");
303         out.shouldContain("java.lang.IncompatibleClassChangeError: class PreloadCircularityTest$Class10b is not implicitly constructible and it is used in a null restricted non-static field (not supported)");
304     }
305 
306     // Testing preloading due to static fields
307 
308     @ImplicitlyConstructible
309     static value class Class50a {
310         @NullRestricted
311         static Class50a sa;
312     }
313 
314     void test_50() throws Exception {
315         OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class50a");
316         out.shouldHaveExitValue(0);
317         out.shouldNotContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class50a");
318     }
319 
320     @ImplicitlyConstructible
321     static value class Class51a {
322         @NullRestricted
323         static Class51b sb;
324 
325         @NullRestricted
326         static Class51c sc;
327     }
328 
329     @ImplicitlyConstructible
330     static value class Class51b {
331         @NullRestricted
332         static Class51a sa;
333     }
334 
335     @ImplicitlyConstructible
336     static value class Class51c {
337         @NullRestricted
338         Class51a sa = new Class51a();
339     }
340 
341     void test_51() throws Exception {
342         OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class51a");
343         out.shouldHaveExitValue(0);
344         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class51b during linking of class PreloadCircularityTest$Class51a. Cause: a null-free static field is declared with this type");
345         out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class51b during linking of class PreloadCircularityTest$Class51a (cause: null-free static field) succeeded");
346         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class51c during linking of class PreloadCircularityTest$Class51a. Cause: a null-free static field is declared with this type");
347         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class51a during loading of class PreloadCircularityTest$Class51c. Cause: a null-free non-static field is declared with this type");
348         out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class51a during loading of class PreloadCircularityTest$Class51c (cause: null-free non-static field) succeeded");
349         out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class51c during linking of class PreloadCircularityTest$Class51a (cause: null-free static field) succeeded");
350         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class51a during linking of class PreloadCircularityTest$Class51b. Cause: a null-free static field is declared with this type");
351         out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class51a during linking of class PreloadCircularityTest$Class51b (cause: null-free static field) succeeded");
352     }
353 
354     static value class Class52a {
355         @NullRestricted
356         static Class52b vb;
357     }
358 
359     @ImplicitlyConstructible
360     static value class Class52b {
361         @NullRestricted
362         Class52c vc = new Class52c();
363     }
364 
365     @ImplicitlyConstructible
366     static value class Class52c {
367         @NullRestricted
368         Class52b vb = new Class52b();
369     }
370 
371     void test_52() throws Exception {
372         OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class52a");
373         out.shouldHaveExitValue(1);
374         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class52b during linking of class PreloadCircularityTest$Class52a. Cause: a null-free static field is declared with this type");
375         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class52c during loading of class PreloadCircularityTest$Class52b. Cause: a null-free non-static field is declared with this type");
376         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class52b during loading of class PreloadCircularityTest$Class52c. Cause: a null-free non-static field is declared with this type");
377         out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class52b during loading of class PreloadCircularityTest$Class52c (cause: null-free non-static field) failed: java/lang/ClassCircularityError");
378         out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class52c during loading of class PreloadCircularityTest$Class52b (cause: null-free non-static field) failed: java/lang/ClassCircularityError");
379     }
380 
381     @ImplicitlyConstructible
382     static value class Class53a {
383         Class53b vb = new Class53b();
384 
385         @NullRestricted
386         static Class53b sb;
387     }
388 
389     @ImplicitlyConstructible
390     static value class Class53b {
391         @NullRestricted
392         Class53a va = new Class53a();
393     }
394 
395     // In the following test, Class53a fails to optimistically load Class53b at load time, but successfully loads it at link time
396 
397     void test_53() throws Exception {
398         OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class53a");
399         out.shouldHaveExitValue(0);
400         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class53b during loading of class PreloadCircularityTest$Class53a. Cause: field type in Preload attribute");
401         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class53a during loading of class PreloadCircularityTest$Class53b. Cause: a null-free non-static field is declared with this type");
402         out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class53a during loading of class PreloadCircularityTest$Class53b (cause: null-free non-static field) failed: java/lang/ClassCircularityError");
403         out.shouldContain("[warning][class,preload] Preloading of class PreloadCircularityTest$Class53b during loading of class PreloadCircularityTest$Class53a (cause: field type in Preload attribute) failed : java/lang/ClassCircularityError");
404         out.shouldContain("[info   ][class,preload] Preloading class PreloadCircularityTest$Class53b during linking of class PreloadCircularityTest$Class53a. Cause: a null-free static field is declared with this type");
405         out.shouldContain("[info   ][class,preload] Preloading class PreloadCircularityTest$Class53a during loading of class PreloadCircularityTest$Class53b. Cause: a null-free non-static field is declared with this type");
406         out.shouldContain("[info   ][class,preload] Preloading of class PreloadCircularityTest$Class53a during loading of class PreloadCircularityTest$Class53b (cause: null-free non-static field) succeeded");
407         out.shouldContain("[info   ][class,preload] Preloading of class PreloadCircularityTest$Class53b during linking of class PreloadCircularityTest$Class53a (cause: null-free static field) succeeded");
408     }
409 
410     static value class Class54a {
411         @NullRestricted
412         static Class54b sb;
413     }
414 
415     static class Class54b { }
416 
417     void test_54() throws Exception {
418         OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class54a");
419         out.shouldHaveExitValue(1);
420         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class54b during linking of class PreloadCircularityTest$Class54a. Cause: a null-free static field is declared with this type");
421         out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class54b during linking of class PreloadCircularityTest$Class54a (cause: null-free static field) succeeded");
422         out.shouldContain("java.lang.IncompatibleClassChangeError: class PreloadCircularityTest$Class54a expects class PreloadCircularityTest$Class54b to be a value class but it is an identity class");
423     }
424 
425     static class Class55a {
426         @NullRestricted
427         static Class55b sb;
428     }
429 
430     static value class Class55b { }
431 
432     void test_55() throws Exception {
433         OutputAnalyzer out = tryLoadingClass("PreloadCircularityTest$Class55a");
434         out.shouldHaveExitValue(1);
435         out.shouldContain("[info][class,preload] Preloading class PreloadCircularityTest$Class55b during linking of class PreloadCircularityTest$Class55a. Cause: a null-free static field is declared with this type");
436         out.shouldContain("[info][class,preload] Preloading of class PreloadCircularityTest$Class55b during linking of class PreloadCircularityTest$Class55a (cause: null-free static field) succeeded");
437         out.shouldContain("java.lang.IncompatibleClassChangeError: class PreloadCircularityTest$Class55b is not implicitly constructible and it is used in a null restricted static field (not supported)");
438     }
439 
440     public static class TestHelper {
441         public static void main(String[] args) {
442             try {
443                 Class c = Class.forName(args[0]);
444             } catch (Throwable ex) {
445                 ex.printStackTrace();
446                 System.exit(1);
447             }
448             System.exit(0);
449         }
450     }
451 
452     static OutputAnalyzer tryLoadingClass(String className) throws Exception {
453         ProcessBuilder pb = exec("PreloadCircularityTest$TestHelper", className);
454         OutputAnalyzer out = new OutputAnalyzer(pb.start());
455         System.out.println(out.getOutput());
456         return out;
457     }
458 
459     static ProcessBuilder exec(String... args) throws Exception {
460         List<String> argsList = new ArrayList<>();
461         Collections.addAll(argsList, "--enable-preview");
462         Collections.addAll(argsList, "-Dtest.class.path=" + System.getProperty("test.class.path", "."));
463         Collections.addAll(argsList, "-Xlog:class+preload=info");
464         Collections.addAll(argsList, args);
465         return ProcessTools.createTestJavaProcessBuilder(argsList);
466     }
467 
468     public static void main(String[] args) throws Exception {
469         System.out.println("Crerating tests");
470         PreloadCircularityTest tests = new PreloadCircularityTest();
471         Class c = tests.getClass();
472         System.out.println("Iterating over test methods");
473         boolean hasFailedTest = false;
474         StringBuilder sb = new StringBuilder("Following tests have failed: ");
475         for (Method m : c.getDeclaredMethods()) {
476             if (m.getName().startsWith("test_")) {
477                 boolean failed = false;
478                 try {
479                     System.out.println("Running " + m.getName());
480                     m.invoke(tests);
481                 } catch (Throwable t) {
482                     t.printStackTrace();
483                     failed = true;
484                 }
485                 System.out.println("Test " + m.getName() + " : " + (failed ? "FAILED" : "PASSED"));
486                 hasFailedTest = failed ? true : hasFailedTest;
487                 if (failed) sb.append(m.getName()).append(", ");
488             }
489         }
490         if (hasFailedTest) {
491             throw new RuntimeException(sb.toString());
492         }
493     }
494 }