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