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 24 package compiler.valhalla.inlinetypes; 25 26 import compiler.lib.ir_framework.*; 27 import jdk.test.lib.Asserts; 28 29 import jdk.internal.value.ValueClass; 30 import jdk.internal.vm.annotation.ImplicitlyConstructible; 31 import jdk.internal.vm.annotation.LooselyConsistentValue; 32 import jdk.internal.vm.annotation.NullRestricted; 33 34 import static compiler.valhalla.inlinetypes.InlineTypes.rI; 35 36 /* 37 * @test 38 * @key randomness 39 * @summary Test the handling of fields of unloaded value classes. 40 * @library /test/lib / 41 * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64") 42 * @enablePreview 43 * @modules java.base/jdk.internal.value 44 * java.base/jdk.internal.vm.annotation 45 * @compile hack/GetUnresolvedInlineFieldWrongSignature.java 46 * @compile TestUnloadedInlineTypeField.java 47 * @run main/othervm/timeout=300 compiler.valhalla.inlinetypes.TestUnloadedInlineTypeField 48 */ 49 50 public class TestUnloadedInlineTypeField { 51 // Only prevent loading of classes when testing with C1. Load classes 52 // early when executing with C2 to prevent uncommon traps. It's still 53 // beneficial to execute this test with C2 because it also checks handling 54 // of type mismatches. 55 56 public static void main(String[] args) { 57 final Scenario[] scenarios = { 58 new Scenario(0), 59 new Scenario(1, "-XX:InlineFieldMaxFlatSize=0"), 60 new Scenario(2, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+PatchALot"), 61 new Scenario(3, "-XX:InlineFieldMaxFlatSize=0", 62 "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+PatchALot") 63 }; 64 InlineTypes.getFramework() 65 .addScenarios(scenarios) 66 .addFlags("--enable-preview", 67 // Prevent IR Test Framework from loading classes 68 "-DIgnoreCompilerControls=true", 69 // Some tests trigger frequent re-compilation. Don't mark them as non-compilable. 70 "-XX:PerMethodRecompilationCutoff=-1", "-XX:PerBytecodeRecompilationCutoff=-1") 71 .start(); 72 } 73 74 // Test case 1: 75 // The value class field class has been loaded, but the holder class has not been loaded. 76 // 77 // aload_0 78 // getfield MyValue1Holder.v:LMyValue1; 79 // ^ not loaded ^ already loaded 80 // 81 // MyValue1 has already been loaded, because it's in the preload attribute of 82 // TestUnloadedInlineTypeField, due to TestUnloadedInlineTypeField.test1_precondition(). 83 @ImplicitlyConstructible 84 @LooselyConsistentValue 85 static value class MyValue1 { 86 int foo; 87 88 MyValue1() { 89 foo = rI; 90 } 91 } 92 93 static class MyValue1Holder { 94 @NullRestricted 95 MyValue1 v; 96 97 public MyValue1Holder() { 98 v = new MyValue1(); 99 } 100 } 101 102 static MyValue1 test1_precondition() { 103 return new MyValue1(); 104 } 105 106 @Test 107 public int test1(Object holder) { 108 if (holder != null) { 109 // Don't use MyValue1Holder in the signature, it might trigger class loading 110 return ((MyValue1Holder)holder).v.foo; 111 } else { 112 return 0; 113 } 114 } 115 116 @Run(test = "test1") 117 public void test1_verifier(RunInfo info) { 118 if (info.isWarmUp() && !info.isC2CompilationEnabled()) { 119 test1(null); 120 } else { 121 MyValue1Holder holder = new MyValue1Holder(); 122 Asserts.assertEQ(test1(holder), rI); 123 } 124 } 125 126 // Test case 2: 127 // Both the value class field class, and the holder class have not been loaded. 128 // 129 // aload_0 130 // getfield MyValue2Holder.v:LMyValue2; 131 // ^ not loaded ^ not loaded 132 // 133 // MyValue2 has not been loaded, because it is not explicitly referenced by 134 // TestUnloadedInlineTypeField. 135 @ImplicitlyConstructible 136 @LooselyConsistentValue 137 static value class MyValue2 { 138 int foo; 139 140 public MyValue2(int n) { 141 foo = n; 142 } 143 } 144 145 static class MyValue2Holder { 146 @NullRestricted 147 MyValue2 v; 148 149 public MyValue2Holder() { 150 v = new MyValue2(rI); 151 } 152 } 153 154 @Test 155 public int test2(Object holder) { 156 if (holder != null) { 157 // Don't use MyValue2Holder in the signature, it might trigger class loading 158 return ((MyValue2Holder)holder).v.foo; 159 } else { 160 return 0; 161 } 162 } 163 164 @Run(test = "test2") 165 public void test2_verifier(RunInfo info) { 166 if (info.isWarmUp() && !info.isC2CompilationEnabled()) { 167 test2(null); 168 } else { 169 MyValue2Holder holder = new MyValue2Holder(); 170 Asserts.assertEQ(test2(holder), rI); 171 } 172 } 173 174 // Test case 4: 175 // Same as case 1, except we use putfield instead of getfield. 176 @ImplicitlyConstructible 177 @LooselyConsistentValue 178 static value class MyValue4 { 179 int foo; 180 181 MyValue4(int n) { 182 foo = n; 183 } 184 } 185 186 static class MyValue4Holder { 187 @NullRestricted 188 MyValue4 v; 189 190 public MyValue4Holder() { 191 v = new MyValue4(0); 192 } 193 } 194 195 @Test 196 public void test4(Object holder, MyValue4 v) { 197 if (holder != null) { 198 // Don't use MyValue4Holder in the signature, it might trigger class loading 199 ((MyValue4Holder)holder).v = v; 200 } 201 } 202 203 @Run(test = "test4") 204 public void test4_verifier(RunInfo info) { 205 MyValue4 v = new MyValue4(rI); 206 if (info.isWarmUp() && !info.isC2CompilationEnabled()) { 207 test4(null, v); 208 } else { 209 MyValue4Holder holder = new MyValue4Holder(); 210 test4(holder, v); 211 Asserts.assertEQ(holder.v.foo, rI); 212 } 213 } 214 215 // Test case 5: 216 // Same as case 2, except we use putfield instead of getfield. 217 @ImplicitlyConstructible 218 @LooselyConsistentValue 219 static value class MyValue5 { 220 int foo; 221 222 MyValue5(int n) { 223 foo = n; 224 } 225 } 226 227 static class MyValue5Holder { 228 @NullRestricted 229 MyValue5 v; 230 231 public MyValue5Holder() { 232 v = new MyValue5(0); 233 } 234 235 public Object make(int n) { 236 return new MyValue5(n); 237 } 238 } 239 240 @Test 241 public void test5(Object holder, Object o) { 242 if (holder != null) { 243 // Don't use MyValue5 and MyValue5Holder in the signature, it might trigger class loading 244 MyValue5 v = (MyValue5)o; 245 ((MyValue5Holder)holder).v = v; 246 } 247 } 248 249 @Run(test = "test5") 250 public void test5_verifier(RunInfo info) { 251 if (info.isWarmUp() && !info.isC2CompilationEnabled()) { 252 test5(null, null); 253 } else { 254 MyValue5Holder holder = new MyValue5Holder(); 255 Object v = holder.make(rI); 256 test5(holder, v); 257 Asserts.assertEQ(holder.v.foo, rI); 258 } 259 } 260 261 262 // Test case 6: (same as test1, except we use getstatic instead of getfield) 263 // The value class field class has been loaded, but the holder class has not been loaded. 264 // 265 // getstatic MyValue6Holder.v:LMyValue1; 266 // ^ not loaded ^ already loaded 267 // 268 // MyValue6 has already been loaded, because it's in the preload attribute of 269 // TestUnloadedInlineTypeField, due to TestUnloadedInlineTypeField.test1_precondition(). 270 @ImplicitlyConstructible 271 @LooselyConsistentValue 272 static value class MyValue6 { 273 int foo; 274 275 MyValue6() { 276 foo = rI; 277 } 278 } 279 280 static class MyValue6Holder { 281 @NullRestricted 282 static MyValue6 v = new MyValue6(); 283 } 284 285 static MyValue6 test6_precondition() { 286 return new MyValue6(); 287 } 288 289 @Test 290 public int test6(int n) { 291 if (n == 0) { 292 return 0; 293 } else { 294 return MyValue6Holder.v.foo + n; 295 } 296 } 297 298 @Run(test = "test6") 299 public void test6_verifier(RunInfo info) { 300 if (info.isWarmUp() && !info.isC2CompilationEnabled()) { 301 test6(0); 302 } else { 303 Asserts.assertEQ(test6(rI), 2*rI); 304 } 305 } 306 307 308 // Test case 7: (same as test2, except we use getstatic instead of getfield) 309 // Both the value class field class, and the holder class have not been loaded. 310 // 311 // getstatic MyValue7Holder.v:LMyValue7; 312 // ^ not loaded ^ not loaded 313 // 314 // MyValue7 has not been loaded, because it is not explicitly referenced by 315 // TestUnloadedInlineTypeField. 316 @ImplicitlyConstructible 317 @LooselyConsistentValue 318 static value class MyValue7 { 319 int foo; 320 321 MyValue7(int n) { 322 foo = n; 323 } 324 } 325 326 static class MyValue7Holder { 327 @NullRestricted 328 static MyValue7 v = new MyValue7(rI); 329 } 330 331 @Test 332 public int test7(int n) { 333 if (n == 0) { 334 return 0; 335 } else { 336 return MyValue7Holder.v.foo + n; 337 } 338 } 339 340 @Run(test = "test7") 341 public void test7_verifier(RunInfo info) { 342 if (info.isWarmUp() && !info.isC2CompilationEnabled()) { 343 test7(0); 344 } else { 345 Asserts.assertEQ(test7(rI), 2*rI); 346 } 347 } 348 349 // Test case 8: 350 // Same as case 1, except holder is allocated in test method (-> no holder null check required) 351 @ImplicitlyConstructible 352 @LooselyConsistentValue 353 static value class MyValue8 { 354 int foo; 355 356 MyValue8() { 357 foo = rI; 358 } 359 } 360 361 static class MyValue8Holder { 362 @NullRestricted 363 MyValue8 v; 364 365 public MyValue8Holder() { 366 v = new MyValue8(); 367 } 368 } 369 370 static MyValue8 test8_precondition() { 371 return new MyValue8(); 372 } 373 374 @Test 375 public int test8(boolean warmup) { 376 if (!warmup) { 377 MyValue8Holder holder = new MyValue8Holder(); 378 return holder.v.foo; 379 } else { 380 return 0; 381 } 382 } 383 384 @Run(test = "test8") 385 public void test8_verifier(RunInfo info) { 386 if (info.isWarmUp() && !info.isC2CompilationEnabled()) { 387 test8(true); 388 } else { 389 Asserts.assertEQ(test8(false), rI); 390 } 391 } 392 393 // Test case 9: 394 // Same as case 2, except holder is allocated in test method (-> no holder null check required) 395 @ImplicitlyConstructible 396 @LooselyConsistentValue 397 static value class MyValue9 { 398 int foo; 399 400 public MyValue9(int n) { 401 foo = n; 402 } 403 } 404 405 static class MyValue9Holder { 406 @NullRestricted 407 MyValue9 v; 408 409 public MyValue9Holder() { 410 v = new MyValue9(rI); 411 } 412 } 413 414 @Test 415 public int test9(boolean warmup) { 416 if (!warmup) { 417 MyValue9Holder holder = new MyValue9Holder(); 418 return holder.v.foo; 419 } else { 420 return 0; 421 } 422 } 423 424 @Run(test = "test9") 425 public void test9_verifier(RunInfo info) { 426 if (info.isWarmUp() && !info.isC2CompilationEnabled()) { 427 test9(true); 428 } else { 429 Asserts.assertEQ(test9(false), rI); 430 } 431 } 432 433 // Test case 11: 434 // Same as case 4, except holder is allocated in test method (-> no holder null check required) 435 @ImplicitlyConstructible 436 @LooselyConsistentValue 437 static value class MyValue11 { 438 int foo; 439 440 MyValue11(int n) { 441 foo = n; 442 } 443 } 444 445 static class MyValue11Holder { 446 @NullRestricted 447 MyValue11 v; 448 449 public MyValue11Holder() { 450 v = new MyValue11(0); 451 } 452 } 453 454 @Test 455 public Object test11(boolean warmup, MyValue11 v) { 456 if (!warmup) { 457 MyValue11Holder holder = new MyValue11Holder(); 458 holder.v = v; 459 return holder; 460 } else { 461 return null; 462 } 463 } 464 465 @Run(test = "test11") 466 public void test11_verifier(RunInfo info) { 467 MyValue11 v = new MyValue11(rI); 468 if (info.isWarmUp() && !info.isC2CompilationEnabled()) { 469 test11(true, v); 470 } else { 471 MyValue11Holder holder = (MyValue11Holder)test11(false, v); 472 Asserts.assertEQ(holder.v.foo, rI); 473 } 474 } 475 476 // Test case 12: 477 // Same as case 5, except holder is allocated in test method (-> no holder null check required) 478 @ImplicitlyConstructible 479 @LooselyConsistentValue 480 static value class MyValue12 { 481 int foo; 482 483 MyValue12(int n) { 484 foo = n; 485 } 486 } 487 488 static class MyValue12Holder { 489 @NullRestricted 490 MyValue12 v; 491 492 public MyValue12Holder() { 493 v = new MyValue12(0); 494 } 495 } 496 497 @Test 498 public Object test12(boolean warmup, Object o) { 499 if (!warmup) { 500 // Don't use MyValue12 in the signature, it might trigger class loading 501 MyValue12Holder holder = new MyValue12Holder(); 502 holder.v = (MyValue12)o; 503 return holder; 504 } else { 505 return null; 506 } 507 } 508 509 @Run(test = "test12") 510 public void test12_verifier(RunInfo info) { 511 if (info.isWarmUp() && !info.isC2CompilationEnabled()) { 512 test12(true, null); 513 } else { 514 MyValue12 v = new MyValue12(rI); 515 MyValue12Holder holder = (MyValue12Holder)test12(false, v); 516 Asserts.assertEQ(holder.v.foo, rI); 517 } 518 } 519 520 // Test case 13: 521 // Same as case 10, except MyValue13 is allocated in test method 522 @ImplicitlyConstructible 523 @LooselyConsistentValue 524 static value class MyValue13 { 525 int foo; 526 527 public MyValue13() { 528 foo = rI; 529 } 530 } 531 532 static class MyValue13Holder { 533 @NullRestricted 534 MyValue13 v; 535 536 public MyValue13Holder() { 537 v = new MyValue13(); 538 } 539 } 540 541 static MyValue13 test13_precondition() { 542 return new MyValue13(); 543 } 544 545 @Test 546 public void test13(Object holder) { 547 // Don't use MyValue13Holder in the signature, it might trigger class loading 548 GetUnresolvedInlineFieldWrongSignature.test13(holder); 549 } 550 551 @Run(test = "test13") 552 public void test13_verifier(RunInfo info) { 553 if (info.isWarmUp() && !info.isC2CompilationEnabled()) { 554 test13(null); 555 } else { 556 // Make sure klass is resolved 557 for (int i = 0; i < 10; ++i) { 558 test13(new MyValue13Holder()); 559 } 560 } 561 } 562 563 // Test case 15: 564 // Same as case 13, except MyValue15 is unloaded 565 @ImplicitlyConstructible 566 @LooselyConsistentValue 567 static value class MyValue15 { 568 int foo; 569 570 public MyValue15() { 571 foo = rI; 572 } 573 } 574 575 static class MyValue15Holder { 576 @NullRestricted 577 MyValue15 v; 578 579 public MyValue15Holder() { 580 v = new MyValue15(); 581 } 582 } 583 584 @Test 585 public void test15(Object holder) { 586 // Don't use MyValue15Holder in the signature, it might trigger class loading 587 GetUnresolvedInlineFieldWrongSignature.test15(holder); 588 } 589 590 @Run(test = "test15") 591 public void test15_verifier(RunInfo info) { 592 if (info.isWarmUp() && !info.isC2CompilationEnabled()) { 593 test15(null); 594 } else { 595 // Make sure klass is resolved 596 for (int i = 0; i < 10; ++i) { 597 test15(new MyValue15Holder()); 598 } 599 } 600 } 601 602 // Test case 16: 603 // aconst_init with type which is not a value class 604 static class MyValue16 { 605 int foo; 606 607 public MyValue16() { 608 foo = rI; 609 } 610 } 611 612 static MyValue16 test16_precondition() { 613 return new MyValue16(); 614 } 615 616 @Test 617 public Object test16(boolean warmup) { 618 return GetUnresolvedInlineFieldWrongSignature.test16(warmup); 619 } 620 621 @Run(test = "test16") 622 public void test16_verifier(RunInfo info) { 623 if (info.isWarmUp() && !info.isC2CompilationEnabled()) { 624 test16(true); 625 } else { 626 // Make sure klass is resolved 627 for (int i = 0; i < 10; ++i) { 628 test16(false); 629 } 630 } 631 } 632 633 // Test case 17: 634 // Same as test16 but with unloaded type at aconst_init 635 static class MyValue17 { 636 int foo; 637 638 public MyValue17() { 639 foo = rI; 640 } 641 } 642 643 @Test 644 public Object test17(boolean warmup) { 645 return GetUnresolvedInlineFieldWrongSignature.test17(warmup); 646 } 647 648 @Run(test = "test17") 649 public void test17_verifier(RunInfo info) { 650 if (info.isWarmUp() && !info.isC2CompilationEnabled()) { 651 test17(true); 652 } else { 653 // Make sure klass is resolved 654 for (int i = 0; i < 10; ++i) { 655 test17(false); 656 } 657 } 658 } 659 660 // Test case 18: 661 // Same as test7 but with the holder being loaded 662 @ImplicitlyConstructible 663 @LooselyConsistentValue 664 static value class MyValue18 { 665 int foo; 666 667 MyValue18(int n) { 668 foo = n; 669 } 670 } 671 672 static class MyValue18Holder { 673 @NullRestricted 674 static MyValue18 v = new MyValue18(rI); 675 } 676 677 @Test 678 public int test18(int n) { 679 if (n == 0) { 680 return 0; 681 } else { 682 return MyValue18Holder.v.foo + n; 683 } 684 } 685 686 @Run(test = "test18") 687 public void test18_verifier(RunInfo info) { 688 // Make sure MyValue18Holder is loaded 689 MyValue18Holder holder = new MyValue18Holder(); 690 if (info.isWarmUp() && !info.isC2CompilationEnabled()) { 691 test18(0); 692 } else { 693 Asserts.assertEQ(test18(rI), 2*rI); 694 } 695 } 696 697 // Test case 19: 698 // Same as test18 but uninitialized (null) static value class field 699 @ImplicitlyConstructible 700 @LooselyConsistentValue 701 static value class MyValue19 { 702 int foo; 703 704 MyValue19(int n) { 705 foo = n; 706 } 707 } 708 709 static class MyValue19Holder { 710 @NullRestricted 711 static MyValue19 v; 712 } 713 714 @Test 715 public int test19(int n) { 716 if (n == 0) { 717 return 0; 718 } else { 719 return MyValue19Holder.v.foo + n; 720 } 721 } 722 723 @Run(test = "test19") 724 public void test19_verifier(RunInfo info) { 725 // Make sure MyValue19Holder is loaded 726 MyValue19Holder holder = new MyValue19Holder(); 727 if (info.isWarmUp() && !info.isC2CompilationEnabled()) { 728 test19(0); 729 } else { 730 Asserts.assertEQ(test19(rI), rI); 731 } 732 } 733 734 // Test case 20: 735 // Value class with object field of unloaded type. 736 static class MyObject20 { 737 int x = 42; 738 } 739 740 @ImplicitlyConstructible 741 @LooselyConsistentValue 742 static value class MyValue20 { 743 MyObject20 obj; 744 745 MyValue20() { 746 this.obj = null; 747 } 748 } 749 750 @Test 751 public MyValue20 test20() { 752 return new MyValue20(); 753 } 754 755 @Run(test = "test20") 756 public void test20_verifier() { 757 MyValue20 vt = test20(); 758 Asserts.assertEQ(vt.obj, null); 759 } 760 761 @ImplicitlyConstructible 762 @LooselyConsistentValue 763 static value class Test21ClassA { 764 @NullRestricted 765 static Test21ClassB b; 766 @NullRestricted 767 static Test21ClassC c; 768 } 769 770 @ImplicitlyConstructible 771 @LooselyConsistentValue 772 static value class Test21ClassB { 773 static int x = Test21ClassA.c.x; 774 } 775 776 @ImplicitlyConstructible 777 @LooselyConsistentValue 778 static value class Test21ClassC { 779 int x = 42; 780 } 781 782 // Test access to static value class field with unloaded type 783 @Test 784 public Object test21() { 785 return new Test21ClassA(); 786 } 787 788 @Run(test = "test21") 789 public void test21_verifier() { 790 Object ret = test21(); 791 Asserts.assertEQ(Test21ClassA.b.x, 42); 792 Asserts.assertEQ(Test21ClassA.c.x, 42); 793 } 794 795 static boolean test22FailInit = true; 796 797 @ImplicitlyConstructible 798 @LooselyConsistentValue 799 static value class Test22ClassA { 800 int x = 0; 801 @NullRestricted 802 static Test22ClassB b; 803 } 804 805 @ImplicitlyConstructible 806 @LooselyConsistentValue 807 static value class Test22ClassB { 808 int x = 0; 809 static { 810 if (test22FailInit) { 811 throw new RuntimeException("Init failed"); 812 } 813 } 814 } 815 816 // Test that load from static field of uninitialized value class throws an exception 817 @Test 818 public Object test22() { 819 return Test22ClassA.b; 820 } 821 822 @Run(test = "test22") 823 public void test22_verifier() { 824 // Trigger initialization error in Test22ClassB 825 try { 826 Test22ClassB b = new Test22ClassB(); 827 throw new RuntimeException("Should have thrown error during initialization"); 828 } catch (ExceptionInInitializerError | NoClassDefFoundError e) { 829 // Expected 830 } 831 try { 832 test22(); 833 throw new RuntimeException("Should have thrown NoClassDefFoundError"); 834 } catch (NoClassDefFoundError e) { 835 // Expected 836 } 837 } 838 839 static boolean test23FailInit = true; 840 841 @ImplicitlyConstructible 842 @LooselyConsistentValue 843 static value class Test23ClassA { 844 int x = 0; 845 @NullRestricted 846 static Test23ClassB b; 847 } 848 849 @ImplicitlyConstructible 850 @LooselyConsistentValue 851 static value class Test23ClassB { 852 static { 853 if (test23FailInit) { 854 throw new RuntimeException("Init failed"); 855 } 856 } 857 } 858 859 // Same as test22 but with empty ClassB 860 @Test 861 public Object test23() { 862 return Test23ClassA.b; 863 } 864 865 @Run(test = "test23") 866 public void test23_verifier() { 867 // Trigger initialization error in Test23ClassB 868 try { 869 Test23ClassB b = new Test23ClassB(); 870 throw new RuntimeException("Should have thrown error during initialization"); 871 } catch (ExceptionInInitializerError | NoClassDefFoundError e) { 872 // Expected 873 } 874 try { 875 test23(); 876 throw new RuntimeException("Should have thrown NoClassDefFoundError"); 877 } catch (NoClassDefFoundError e) { 878 // Expected 879 } 880 } 881 882 static boolean test24FailInit = true; 883 884 @ImplicitlyConstructible 885 @LooselyConsistentValue 886 static value class Test24ClassA { 887 @NullRestricted 888 Test24ClassB b = new Test24ClassB(); 889 } 890 891 @ImplicitlyConstructible 892 @LooselyConsistentValue 893 static value class Test24ClassB { 894 int x = 0; 895 static { 896 if (test24FailInit) { 897 throw new RuntimeException("Init failed"); 898 } 899 } 900 } 901 902 // Test that access to non-static field of uninitialized value class throws an exception 903 @Test 904 public Object test24() { 905 return (new Test24ClassA()).b.x; 906 } 907 908 @Run(test = "test24") 909 public void test24_verifier() { 910 // Trigger initialization error in Test24ClassB 911 try { 912 Test24ClassB b = new Test24ClassB(); 913 throw new RuntimeException("Should have thrown error during initialization"); 914 } catch (ExceptionInInitializerError | NoClassDefFoundError e) { 915 // Expected 916 } 917 try { 918 test24(); 919 throw new RuntimeException("Should have thrown NoClassDefFoundError"); 920 } catch (NoClassDefFoundError e) { 921 // Expected 922 } 923 } 924 925 static boolean test25FailInit = true; 926 927 @ImplicitlyConstructible 928 @LooselyConsistentValue 929 static value class Test25ClassA { 930 @NullRestricted 931 Test25ClassB b = new Test25ClassB(); 932 } 933 934 @ImplicitlyConstructible 935 @LooselyConsistentValue 936 static value class Test25ClassB { 937 int x = 24; 938 static { 939 if (test25FailInit) { 940 throw new RuntimeException("Init failed"); 941 } 942 } 943 } 944 945 // Same as test24 but with field access outside of test method 946 @Test 947 public Test25ClassB test25() { 948 return (new Test25ClassA()).b; 949 } 950 951 @Run(test = "test25") 952 public void test25_verifier() { 953 // Trigger initialization error in Test25ClassB 954 try { 955 Test25ClassB b = new Test25ClassB(); 956 throw new RuntimeException("Should have thrown error during initialization"); 957 } catch (ExceptionInInitializerError | NoClassDefFoundError e) { 958 // Expected 959 } 960 try { 961 Test25ClassB res = test25(); 962 Asserts.assertEQ(res.x, 0); 963 throw new RuntimeException("Should have thrown NoClassDefFoundError"); 964 } catch (NoClassDefFoundError e) { 965 // Expected 966 } 967 } 968 969 static boolean test26FailInit = true; 970 971 @ImplicitlyConstructible 972 @LooselyConsistentValue 973 static value class Test26ClassA { 974 @NullRestricted 975 Test26ClassB b = new Test26ClassB(); 976 } 977 978 @ImplicitlyConstructible 979 @LooselyConsistentValue 980 static value class Test26ClassB { 981 static { 982 if (test26FailInit) { 983 throw new RuntimeException("Init failed"); 984 } 985 } 986 } 987 988 // Same as test25 but with empty ClassB 989 @Test 990 public Object test26() { 991 return (new Test26ClassA()).b; 992 } 993 994 @Run(test = "test26") 995 public void test26_verifier() { 996 // Trigger initialization error in Test26ClassB 997 try { 998 Test26ClassB b = new Test26ClassB(); 999 throw new RuntimeException("Should have thrown error during initialization"); 1000 } catch (ExceptionInInitializerError | NoClassDefFoundError e) { 1001 // Expected 1002 } 1003 try { 1004 test26(); 1005 throw new RuntimeException("Should have thrown NoClassDefFoundError"); 1006 } catch (NoClassDefFoundError e) { 1007 // Expected 1008 } 1009 } 1010 1011 @ImplicitlyConstructible 1012 @LooselyConsistentValue 1013 static value class MyValue27 { 1014 int foo = 42; 1015 } 1016 1017 static class MyValue27Holder { 1018 @NullRestricted 1019 MyValue27 v; 1020 } 1021 1022 // Make sure MyValue27Holder is loaded but MyValue27 is not 1023 Class test27Class = MyValue27Holder.class; 1024 1025 // Test unloaded value class field load from loaded holder 1026 @Test 1027 public static int test27() { 1028 MyValue27Holder holder = new MyValue27Holder(); 1029 return holder.v.foo; 1030 } 1031 1032 @Run(test = "test27") 1033 public void test27_verifier() { 1034 Asserts.assertEQ(test27(), 42); 1035 } 1036 1037 @ImplicitlyConstructible 1038 @LooselyConsistentValue 1039 static value class MyValue28 { 1040 @NullRestricted 1041 static MyValue28 field1; 1042 } 1043 1044 // Test null store to null restricted field with unloaded holder 1045 @Test 1046 public static void test28() { 1047 MyValue28.field1 = null; 1048 } 1049 1050 @Run(test = "test28") 1051 @Warmup(0) // Make sure that MyValue28 is not loaded 1052 public void test28_verifier() { 1053 try { 1054 test28(); 1055 throw new RuntimeException("No exception thrown"); 1056 } catch (NullPointerException e) { 1057 // Expected 1058 } 1059 } 1060 }