1 /* 2 * Copyright (c) 2014, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 * @test TestStableObject 28 * @summary tests on stable fields and arrays 29 * @library /testlibrary /testlibrary/whitebox 30 * @build TestStableObject StableConfiguration sun.hotspot.WhiteBox 31 * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission 32 * @run main ClassFileInstaller 33 * java/lang/invoke/StableConfiguration 34 * java/lang/invoke/TestStableObject 35 * java/lang/invoke/TestStableObject$ObjectStable 36 * java/lang/invoke/TestStableObject$StaticObjectStable 37 * java/lang/invoke/TestStableObject$VolatileObjectStable 38 * java/lang/invoke/TestStableObject$ObjectArrayDim1 39 * java/lang/invoke/TestStableObject$ObjectArrayDim2 40 * java/lang/invoke/TestStableObject$ObjectArrayDim3 41 * java/lang/invoke/TestStableObject$ObjectArrayDim4 42 * java/lang/invoke/TestStableObject$ObjectArrayLowerDim0 43 * java/lang/invoke/TestStableObject$ObjectArrayLowerDim1 44 * java/lang/invoke/TestStableObject$NestedStableField 45 * java/lang/invoke/TestStableObject$NestedStableField$A 46 * java/lang/invoke/TestStableObject$NestedStableField1 47 * java/lang/invoke/TestStableObject$NestedStableField1$A 48 * java/lang/invoke/TestStableObject$NestedStableField2 49 * java/lang/invoke/TestStableObject$NestedStableField2$A 50 * java/lang/invoke/TestStableObject$NestedStableField3 51 * java/lang/invoke/TestStableObject$NestedStableField3$A 52 * java/lang/invoke/TestStableObject$Values 53 * java/lang/invoke/TestStableObject$DefaultValue 54 * java/lang/invoke/TestStableObject$DefaultStaticValue 55 * java/lang/invoke/TestStableObject$ObjectArrayLowerDim2 56 * 57 * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions 58 * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp 59 * -server -XX:-TieredCompilation 60 * -XX:+FoldStableValues 61 * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 62 * java.lang.invoke.TestStableObject 63 * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions 64 * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp 65 * -server -XX:-TieredCompilation 66 * -XX:-FoldStableValues 67 * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 68 * java.lang.invoke.TestStableObject 69 * 70 * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions 71 * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp 72 * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 73 * -XX:+FoldStableValues 74 * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 75 * java.lang.invoke.TestStableObject 76 * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions 77 * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp 78 * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 79 * -XX:-FoldStableValues 80 * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 81 * java.lang.invoke.TestStableObject 82 * 83 * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions 84 * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp 85 * -client -XX:-TieredCompilation 86 * -XX:+FoldStableValues 87 * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 88 * java.lang.invoke.TestStableObject 89 * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions 90 * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp 91 * -client -XX:-TieredCompilation 92 * -XX:-FoldStableValues 93 * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 94 * java.lang.invoke.TestStableObject 95 */ 96 package java.lang.invoke; 97 98 import java.lang.reflect.InvocationTargetException; 99 100 public class TestStableObject { 101 static final boolean isStableEnabled = StableConfiguration.isStableEnabled; 102 static final boolean isServerWithStable = StableConfiguration.isServerWithStable; 103 104 public static void main(String[] args) throws Exception { 105 run(DefaultValue.class); 106 run(ObjectStable.class); 107 run(DefaultStaticValue.class); 108 run(StaticObjectStable.class); 109 run(VolatileObjectStable.class); 110 111 // @Stable arrays: Dim 1-4 112 run(ObjectArrayDim1.class); 113 run(ObjectArrayDim2.class); 114 run(ObjectArrayDim3.class); 115 run(ObjectArrayDim4.class); 116 117 // @Stable Object field: dynamic arrays 118 run(ObjectArrayLowerDim0.class); 119 run(ObjectArrayLowerDim1.class); 120 run(ObjectArrayLowerDim2.class); 121 122 // Nested @Stable fields 123 run(NestedStableField.class); 124 run(NestedStableField1.class); 125 run(NestedStableField2.class); 126 run(NestedStableField3.class); 127 128 if (failed) { 129 throw new Error("TEST FAILED"); 130 } 131 } 132 133 /* ==================================================== */ 134 135 enum Values {A, B, C, D, E, F} 136 137 static class DefaultValue { 138 public @Stable Object v; 139 140 public static final DefaultValue c = new DefaultValue(); 141 public static Object get() { return c.v; } 142 public static void test() throws Exception { 143 Object val1 = get(); 144 c.v = Values.A; Object val2 = get(); 145 assertEquals(val1, null); 146 assertEquals(val2, Values.A); 147 } 148 } 149 150 /* ==================================================== */ 151 152 static class ObjectStable { 153 public @Stable Values v; 154 155 public static final ObjectStable c = new ObjectStable (); 156 public static Values get() { return c.v; } 157 public static void test() throws Exception { 158 c.v = Values.A; Values val1 = get(); 159 c.v = Values.B; Values val2 = get(); 160 assertEquals(val1, Values.A); 161 assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); 162 } 163 } 164 165 /* ==================================================== */ 166 167 static class DefaultStaticValue { 168 public static @Stable Object v; 169 170 public static final DefaultStaticValue c = new DefaultStaticValue(); 171 public static Object get() { return c.v; } 172 public static void test() throws Exception { 173 Object val1 = get(); 174 c.v = Values.A; Object val2 = get(); 175 assertEquals(val1, null); 176 assertEquals(val2, Values.A); 177 } 178 } 179 180 /* ==================================================== */ 181 182 static class StaticObjectStable { 183 public static @Stable Values v; 184 185 public static final ObjectStable c = new ObjectStable (); 186 public static Values get() { return c.v; } 187 public static void test() throws Exception { 188 c.v = Values.A; Values val1 = get(); 189 c.v = Values.B; Values val2 = get(); 190 assertEquals(val1, Values.A); 191 assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); 192 } 193 } 194 195 /* ==================================================== */ 196 197 static class VolatileObjectStable { 198 public @Stable volatile Values v; 199 200 public static final VolatileObjectStable c = new VolatileObjectStable (); 201 public static Values get() { return c.v; } 202 public static void test() throws Exception { 203 c.v = Values.A; Values val1 = get(); 204 c.v = Values.B; Values val2 = get(); 205 assertEquals(val1, Values.A); 206 assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); 207 } 208 } 209 210 /* ==================================================== */ 211 // @Stable array == field && all components are stable 212 213 static class ObjectArrayDim1 { 214 public @Stable Object[] v; 215 216 public static final ObjectArrayDim1 c = new ObjectArrayDim1(); 217 public static Object get() { return c.v[0]; } 218 public static Object get1() { return c.v[10]; } 219 public static Object[] get2() { return c.v; } 220 public static void test() throws Exception { 221 { 222 c.v = new Object[1]; c.v[0] = Values.A; Object val1 = get(); 223 c.v[0] = Values.B; Object val2 = get(); 224 assertEquals(val1, Values.A); 225 assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); 226 227 c.v = new Object[1]; c.v[0] = Values.C; Object val3 = get(); 228 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) 229 : Values.C)); 230 } 231 232 { 233 c.v = new Object[20]; c.v[10] = Values.A; Object val1 = get1(); 234 c.v[10] = Values.B; Object val2 = get1(); 235 assertEquals(val1, Values.A); 236 assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); 237 238 c.v = new Object[20]; c.v[10] = Values.C; Object val3 = get1(); 239 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) 240 : Values.C)); 241 } 242 243 { 244 c.v = new Object[1]; Object[] val1 = get2(); 245 c.v = new Object[1]; Object[] val2 = get2(); 246 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 247 } 248 } 249 } 250 251 /* ==================================================== */ 252 253 static class ObjectArrayDim2 { 254 public @Stable Object[][] v; 255 256 public static final ObjectArrayDim2 c = new ObjectArrayDim2(); 257 public static Object get() { return c.v[0][0]; } 258 public static Object[] get1() { return c.v[0]; } 259 public static Object[][] get2() { return c.v; } 260 public static void test() throws Exception { 261 { 262 c.v = new Object[1][1]; c.v[0][0] = Values.A; Object val1 = get(); 263 c.v[0][0] = Values.B; Object val2 = get(); 264 assertEquals(val1, Values.A); 265 assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); 266 267 c.v = new Object[1][1]; c.v[0][0] = Values.C; Object val3 = get(); 268 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) 269 : Values.C)); 270 271 c.v[0] = new Object[1]; c.v[0][0] = Values.D; Object val4 = get(); 272 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) 273 : Values.D)); 274 } 275 276 { 277 c.v = new Object[1][1]; Object[] val1 = get1(); 278 c.v[0] = new Object[1]; Object[] val2 = get1(); 279 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); 280 } 281 282 { 283 c.v = new Object[1][1]; Object[][] val1 = get2(); 284 c.v = new Object[1][1]; Object[][] val2 = get2(); 285 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 286 } 287 } 288 } 289 290 /* ==================================================== */ 291 292 static class ObjectArrayDim3 { 293 public @Stable Object[][][] v; 294 295 public static final ObjectArrayDim3 c = new ObjectArrayDim3(); 296 public static Object get() { return c.v[0][0][0]; } 297 public static Object[] get1() { return c.v[0][0]; } 298 public static Object[][] get2() { return c.v[0]; } 299 public static Object[][][] get3() { return c.v; } 300 public static void test() throws Exception { 301 { 302 c.v = new Object[1][1][1]; c.v[0][0][0] = Values.A; Object val1 = get(); 303 c.v[0][0][0] = Values.B; Object val2 = get(); 304 assertEquals(val1, Values.A); 305 assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); 306 307 c.v = new Object[1][1][1]; c.v[0][0][0] = Values.C; Object val3 = get(); 308 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) 309 : Values.C)); 310 311 c.v[0] = new Object[1][1]; c.v[0][0][0] = Values.D; Object val4 = get(); 312 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) 313 : Values.D)); 314 315 c.v[0][0] = new Object[1]; c.v[0][0][0] = Values.E; Object val5 = get(); 316 assertEquals(val5, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) 317 : Values.E)); 318 } 319 320 { 321 c.v = new Object[1][1][1]; Object[] val1 = get1(); 322 c.v[0][0] = new Object[1]; Object[] val2 = get1(); 323 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); 324 } 325 326 { 327 c.v = new Object[1][1][1]; Object[][] val1 = get2(); 328 c.v[0] = new Object[1][1]; Object[][] val2 = get2(); 329 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); 330 } 331 332 { 333 c.v = new Object[1][1][1]; Object[][][] val1 = get3(); 334 c.v = new Object[1][1][1]; Object[][][] val2 = get3(); 335 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 336 } 337 } 338 } 339 340 /* ==================================================== */ 341 342 static class ObjectArrayDim4 { 343 public @Stable Object[][][][] v; 344 345 public static final ObjectArrayDim4 c = new ObjectArrayDim4(); 346 public static Object get() { return c.v[0][0][0][0]; } 347 public static Object[] get1() { return c.v[0][0][0]; } 348 public static Object[][] get2() { return c.v[0][0]; } 349 public static Object[][][] get3() { return c.v[0]; } 350 public static Object[][][][] get4() { return c.v; } 351 public static void test() throws Exception { 352 { 353 c.v = new Object[1][1][1][1]; c.v[0][0][0][0] = Values.A; Object val1 = get(); 354 c.v[0][0][0][0] = Values.B; Object val2 = get(); 355 assertEquals(val1, Values.A); 356 assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); 357 358 c.v = new Object[1][1][1][1]; c.v[0][0][0][0] = Values.C; Object val3 = get(); 359 assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) 360 : Values.C)); 361 362 c.v[0] = new Object[1][1][1]; c.v[0][0][0][0] = Values.D; Object val4 = get(); 363 assertEquals(val4, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) 364 : Values.D)); 365 366 c.v[0][0] = new Object[1][1]; c.v[0][0][0][0] = Values.E; Object val5 = get(); 367 assertEquals(val5, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) 368 : Values.E)); 369 370 c.v[0][0][0] = new Object[1]; c.v[0][0][0][0] = Values.F; Object val6 = get(); 371 assertEquals(val6, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) 372 : Values.F)); 373 } 374 375 { 376 c.v = new Object[1][1][1][1]; Object[] val1 = get1(); 377 c.v[0][0][0] = new Object[1]; Object[] val2 = get1(); 378 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); 379 } 380 381 { 382 c.v = new Object[1][1][1][1]; Object[][] val1 = get2(); 383 c.v[0][0] = new Object[1][1]; Object[][] val2 = get2(); 384 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); 385 } 386 387 { 388 c.v = new Object[1][1][1][1]; Object[][][] val1 = get3(); 389 c.v[0] = new Object[1][1][1]; Object[][][] val2 = get3(); 390 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); 391 } 392 393 { 394 c.v = new Object[1][1][1][1]; Object[][][][] val1 = get4(); 395 c.v = new Object[1][1][1][1]; Object[][][][] val2 = get4(); 396 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 397 } 398 } 399 } 400 401 /* ==================================================== */ 402 // Dynamic Dim is higher than static 403 static class ObjectArrayLowerDim0 { 404 public @Stable Object v; 405 406 public static final ObjectArrayLowerDim0 c = new ObjectArrayLowerDim0(); 407 public static Object get() { return ((Object[])c.v)[0]; } 408 public static Object[] get1() { return (Object[])c.v; } 409 410 public static void test() throws Exception { 411 { 412 c.v = new Object[1]; ((Object[])c.v)[0] = Values.A; Object val1 = get(); 413 ((Object[])c.v)[0] = Values.B; Object val2 = get(); 414 415 assertEquals(val1, Values.A); 416 assertEquals(val2, Values.B); 417 } 418 419 { 420 c.v = new Object[1]; Object[] val1 = get1(); 421 c.v = new Object[1]; Object[] val2 = get1(); 422 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 423 } 424 } 425 } 426 427 /* ==================================================== */ 428 429 static class ObjectArrayLowerDim1 { 430 public @Stable Object[] v; 431 432 public static final ObjectArrayLowerDim1 c = new ObjectArrayLowerDim1(); 433 public static Object get() { return ((Object[][])c.v)[0][0]; } 434 public static Object[] get1() { return (Object[])(c.v[0]); } 435 public static Object[] get2() { return c.v; } 436 437 public static void test() throws Exception { 438 { 439 c.v = new Object[1][1]; ((Object[][])c.v)[0][0] = Values.A; Object val1 = get(); 440 ((Object[][])c.v)[0][0] = Values.B; Object val2 = get(); 441 442 assertEquals(val1, Values.A); 443 assertEquals(val2, Values.B); 444 } 445 446 { 447 c.v = new Object[1][1]; c.v[0] = new Object[0]; Object[] val1 = get1(); 448 c.v[0] = new Object[0]; Object[] val2 = get1(); 449 450 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); 451 } 452 453 { 454 c.v = new Object[0][0]; Object[] val1 = get2(); 455 c.v = new Object[0][0]; Object[] val2 = get2(); 456 457 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 458 } 459 } 460 } 461 462 /* ==================================================== */ 463 464 static class ObjectArrayLowerDim2 { 465 public @Stable Object[][] v; 466 467 public static final ObjectArrayLowerDim2 c = new ObjectArrayLowerDim2(); 468 public static Object get() { return ((Object[][][])c.v)[0][0][0]; } 469 public static Object[] get1() { return (Object[])(c.v[0][0]); } 470 public static Object[][] get2() { return (Object[][])(c.v[0]); } 471 public static Object[][] get3() { return c.v; } 472 473 public static void test() throws Exception { 474 { 475 c.v = new Object[1][1][1]; ((Object[][][])c.v)[0][0][0] = Values.A; Object val1 = get(); 476 ((Object[][][])c.v)[0][0][0] = Values.B; Object val2 = get(); 477 478 assertEquals(val1, Values.A); 479 assertEquals(val2, Values.B); 480 } 481 482 { 483 c.v = new Object[1][1][1]; c.v[0][0] = new Object[0]; Object[] val1 = get1(); 484 c.v[0][0] = new Object[0]; Object[] val2 = get1(); 485 486 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); 487 } 488 489 { 490 c.v = new Object[1][1][1]; c.v[0] = new Object[0][0]; Object[][] val1 = get2(); 491 c.v[0] = new Object[0][0]; Object[][] val2 = get2(); 492 493 assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); 494 } 495 496 { 497 c.v = new Object[0][0][0]; Object[][] val1 = get3(); 498 c.v = new Object[0][0][0]; Object[][] val2 = get3(); 499 500 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 501 } 502 } 503 } 504 505 /* ==================================================== */ 506 507 static class NestedStableField { 508 static class A { 509 public @Stable Object a; 510 511 } 512 public @Stable A v; 513 514 public static final NestedStableField c = new NestedStableField(); 515 public static A get() { return c.v; } 516 public static Object get1() { return get().a; } 517 518 public static void test() throws Exception { 519 { 520 c.v = new A(); c.v.a = Values.A; A val1 = get(); 521 c.v.a = Values.B; A val2 = get(); 522 523 assertEquals(val1.a, Values.B); 524 assertEquals(val2.a, Values.B); 525 } 526 527 { 528 c.v = new A(); c.v.a = Values.A; Object val1 = get1(); 529 c.v.a = Values.B; Object val2 = get1(); 530 c.v = new A(); c.v.a = Values.C; Object val3 = get1(); 531 532 assertEquals(val1, Values.A); 533 assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); 534 assertEquals(val3, (isStableEnabled ? Values.A : Values.C)); 535 } 536 } 537 } 538 539 /* ==================================================== */ 540 541 static class NestedStableField1 { 542 static class A { 543 public @Stable Object a; 544 public @Stable A next; 545 } 546 public @Stable A v; 547 548 public static final NestedStableField1 c = new NestedStableField1(); 549 public static A get() { return c.v.next.next.next.next.next.next.next; } 550 public static Object get1() { return get().a; } 551 552 public static void test() throws Exception { 553 { 554 c.v = new A(); c.v.next = new A(); c.v.next.next = c.v; 555 c.v.a = Values.A; c.v.next.a = Values.A; A val1 = get(); 556 c.v.a = Values.B; c.v.next.a = Values.B; A val2 = get(); 557 558 assertEquals(val1.a, Values.B); 559 assertEquals(val2.a, Values.B); 560 } 561 562 { 563 c.v = new A(); c.v.next = c.v; 564 c.v.a = Values.A; Object val1 = get1(); 565 c.v.a = Values.B; Object val2 = get1(); 566 c.v = new A(); c.v.next = c.v; 567 c.v.a = Values.C; Object val3 = get1(); 568 569 assertEquals(val1, Values.A); 570 assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); 571 assertEquals(val3, (isStableEnabled ? Values.A : Values.C)); 572 } 573 } 574 } 575 /* ==================================================== */ 576 577 static class NestedStableField2 { 578 static class A { 579 public @Stable Object a; 580 public @Stable A left; 581 public A right; 582 } 583 584 public @Stable A v; 585 586 public static final NestedStableField2 c = new NestedStableField2(); 587 public static Object get() { return c.v.left.left.left.a; } 588 public static Object get1() { return c.v.left.left.right.left.a; } 589 590 public static void test() throws Exception { 591 { 592 c.v = new A(); c.v.left = c.v.right = c.v; 593 c.v.a = Values.A; Object val1 = get(); Object val2 = get1(); 594 c.v.a = Values.B; Object val3 = get(); Object val4 = get1(); 595 596 assertEquals(val1, Values.A); 597 assertEquals(val3, (isStableEnabled ? Values.A : Values.B)); 598 599 assertEquals(val2, Values.A); 600 assertEquals(val4, Values.B); 601 } 602 } 603 } 604 605 /* ==================================================== */ 606 607 static class NestedStableField3 { 608 static class A { 609 public @Stable Object a; 610 public @Stable A[] left; 611 public A[] right; 612 } 613 614 public @Stable A[] v; 615 616 public static final NestedStableField3 c = new NestedStableField3(); 617 public static Object get() { return c.v[0].left[1].left[0].left[1].a; } 618 public static Object get1() { return c.v[1].left[0].left[1].right[0].left[1].a; } 619 620 public static void test() throws Exception { 621 { 622 A elem = new A(); 623 c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v; 624 elem.a = Values.A; Object val1 = get(); Object val2 = get1(); 625 elem.a = Values.B; Object val3 = get(); Object val4 = get1(); 626 627 assertEquals(val1, Values.A); 628 assertEquals(val3, (isServerWithStable ? Values.A : Values.B)); 629 630 assertEquals(val2, Values.A); 631 assertEquals(val4, Values.B); 632 } 633 } 634 } 635 636 /* ==================================================== */ 637 // Auxiliary methods 638 static void assertEquals(Object i, Object j) { if (i != j) throw new AssertionError(i + " != " + j); } 639 static void assertTrue(boolean b) { if (!b) throw new AssertionError(); } 640 641 static boolean failed = false; 642 643 public static void run(Class<?> test) { 644 Throwable ex = null; 645 System.out.print(test.getName()+": "); 646 try { 647 test.getMethod("test").invoke(null); 648 } catch (InvocationTargetException e) { 649 ex = e.getCause(); 650 } catch (Throwable e) { 651 ex = e; 652 } finally { 653 if (ex == null) { 654 System.out.println("PASSED"); 655 } else { 656 failed = true; 657 System.out.println("FAILED"); 658 ex.printStackTrace(System.out); 659 } 660 } 661 } 662 }