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