1 /* 2 * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2018 SAP SE. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /** 26 * @test 27 * @summary Check that the verbose message of the AME is printed correctly. 28 * @requires !(os.arch=="arm") & vm.flavor == "server" & !vm.emulatedClient & vm.compMode=="Xmixed" & (!vm.graal.enabled | vm.opt.TieredCompilation == true) & (vm.opt.TieredStopAtLevel == null | vm.opt.TieredStopAtLevel==4) 29 * @library /test/lib / 30 * @build sun.hotspot.WhiteBox 31 * @run driver ClassFileInstaller sun.hotspot.WhiteBox 32 * @compile AbstractMethodErrorTest.java 33 * @compile AME1_E.jasm AME2_C.jasm AME3_C.jasm AME4_E.jasm AME5_B.jasm AME6_B.jasm 34 * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI 35 * -XX:CompileThreshold=1000 -XX:-BackgroundCompilation -XX:-Inline 36 * -XX:CompileCommand=exclude,AbstractMethodErrorTest::test_ame1 37 * AbstractMethodErrorTest 38 */ 39 40 import sun.hotspot.WhiteBox; 41 import compiler.whitebox.CompilerWhiteBoxTest; 42 import java.lang.reflect.Method; 43 44 // This test assembles an errorneous installation of classes. 45 // First, compile the test by @compile. This results in a legal set 46 // of classes. 47 // Then, with jasm, generate incompatible classes that overwrite 48 // the class files in the build directory. 49 // Last, call the real test throwing an AbstractMethodError and 50 // check the message generated. 51 public class AbstractMethodErrorTest { 52 53 private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); 54 55 private static boolean enableChecks = true; 56 57 private static boolean compile(Class<?> clazz, String name) { 58 try { 59 Method method = clazz.getMethod(name); 60 boolean enqueued = WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); 61 if (!enqueued) { 62 System.out.println("Warning: Blocking compilation failed for " + clazz.getName() + "." + name + " (timeout?)"); 63 return false; 64 } else if (!WHITE_BOX.isMethodCompiled(method)) { 65 throw new RuntimeException(clazz.getName() + "." + name + " is not compiled"); 66 } 67 } catch (NoSuchMethodException e) { 68 throw new RuntimeException(clazz.getName() + "." + name + " not found", e); 69 } 70 return true; 71 } 72 73 public static boolean setup_test() { 74 // Assure all exceptions are loaded. 75 new AbstractMethodError(); 76 new IncompatibleClassChangeError(); 77 78 enableChecks = false; 79 // Warmup 80 System.out.println("warmup:"); 81 test_ame5_compiled_vtable_stub(); 82 test_ame6_compiled_itable_stub(); 83 enableChecks = true; 84 85 // Compile 86 if (!compile(AbstractMethodErrorTest.class, "test_ame5_compiled_vtable_stub") || 87 !compile(AbstractMethodErrorTest.class, "test_ame6_compiled_itable_stub") || 88 !compile(AME5_C.class, "mc") || 89 !compile(AME5_D.class, "mc") || 90 !compile(AME5_E.class, "mc") || 91 !compile(AME6_C.class, "mc") || 92 !compile(AME6_D.class, "mc") || 93 !compile(AME6_E.class, "mc")) { 94 return false; 95 } 96 97 System.out.println("warmup done."); 98 return true; 99 } 100 101 private static String expectedErrorMessageAME1_1 = 102 "Missing implementation of resolved method 'abstract " + 103 "java.lang.String anAbstractMethod()' of abstract class AME1_B."; 104 private static String expectedErrorMessageAME1_2 = 105 "Receiver class AME1_E does not define or inherit an implementation of the " + 106 "resolved method 'abstract java.lang.String aFunctionOfMyInterface()' of " + 107 "interface AME1_C."; 108 109 public static void test_ame1() { 110 AME1_B objectAbstract = new AME1_D(); 111 AME1_C objectInterface = new AME1_D(); 112 objectInterface.secondFunctionOfMyInterface(); 113 objectAbstract.anAbstractMethod(); 114 objectInterface.aFunctionOfMyInterface(); 115 116 try { 117 objectAbstract = new AME1_E(); 118 // AbstractMethodError gets thrown in the interpreter at: 119 // InterpreterGenerator::generate_abstract_entry 120 objectAbstract.anAbstractMethod(); 121 throw new RuntimeException("Expected AbstractRuntimeError was not thrown."); 122 } catch (AbstractMethodError e) { 123 String errorMsg = e.getMessage(); 124 if (errorMsg == null) { 125 throw new RuntimeException("Caught AbstractMethodError with empty message."); 126 } else if (!errorMsg.equals(expectedErrorMessageAME1_1)) { 127 System.out.println("Expected: " + expectedErrorMessageAME1_1 + "\n" + 128 "but got: " + errorMsg); 129 throw new RuntimeException("Wrong error message of AbstractMethodError."); 130 } 131 } catch (RuntimeException e) { 132 throw e; 133 } catch (Throwable e) { 134 throw new RuntimeException("Caught unexpected exception: " + e); 135 } 136 137 try { 138 objectInterface = new AME1_E(); 139 // AbstractMethodError gets thrown in: 140 // TemplateTable::invokeinterface or C-Interpreter loop 141 objectInterface.aFunctionOfMyInterface(); 142 throw new RuntimeException("Expected AbstractRuntimeError was not thrown."); 143 } catch (AbstractMethodError e) { 144 String errorMsg = e.getMessage(); 145 if (errorMsg == null) { 146 throw new RuntimeException("Caught AbstractMethodError with empty message."); 147 } else if (!errorMsg.equals(expectedErrorMessageAME1_2)) { 148 // Thrown via InterpreterRuntime::throw_AbstractMethodErrorVerbose(). 149 System.out.println("Expected: " + expectedErrorMessageAME1_2 + "\n" + 150 "but got: " + errorMsg); 151 throw new RuntimeException("Wrong error message of AbstractMethodError."); 152 } else { 153 System.out.println("Passed with message: " + errorMsg); 154 } 155 } catch (Throwable e) { 156 throw new RuntimeException("Caught unexpected exception: " + e); 157 } 158 } 159 160 private static String expectedErrorMessageAME2_Interpreted = 161 "Missing implementation of resolved method 'abstract " + 162 "void aFunctionOfMyInterface()' of interface AME2_A."; 163 private static String expectedErrorMessageAME2_Compiled = 164 "Receiver class AME2_C does not define or inherit an implementation of the resolved method " + 165 "'abstract void aFunctionOfMyInterface()' of interface AME2_A."; 166 167 public AbstractMethodErrorTest() throws InstantiationException, IllegalAccessException { 168 try { 169 AME2_B myAbstract = new ImplementsAllFunctions(); 170 myAbstract.fun2(); 171 myAbstract.aFunctionOfMyInterface(); 172 173 // AME2_C does not implement the method 174 // aFunctionOfMyInterface(). Expected runtime behavior is 175 // throwing an AbstractMethodError. 176 // The error will be thrown via throw_AbstractMethodErrorWithMethod() 177 // if the template interpreter calls an abstract method by 178 // entering the abstract method entry. 179 myAbstract = new AME2_C(); 180 myAbstract.fun2(); 181 myAbstract.aFunctionOfMyInterface(); 182 } catch (SecurityException e) { 183 e.printStackTrace(); 184 } 185 } 186 187 // Loop so that method gets eventually compiled/osred. 188 public static void test_ame2() throws Exception { 189 boolean seenInterpreted = false; 190 boolean seenCompiled = false; 191 192 // Loop to test both, the interpreted and the compiled case. 193 for (int i = 0; i < 10000 && !(seenInterpreted && seenCompiled); ++i) { 194 try { 195 // Supposed to throw AME with verbose message. 196 new AbstractMethodErrorTest(); 197 198 throw new RuntimeException("Expected AbstractMethodError was not thrown."); 199 } catch (AbstractMethodError e) { 200 String errorMsg = e.getMessage(); 201 202 // Check the message obtained. 203 if (errorMsg == null) { 204 throw new RuntimeException("Caught AbstractMethodError with empty message."); 205 } else if (errorMsg.equals(expectedErrorMessageAME2_Interpreted)) { 206 seenInterpreted = true; 207 } else if (errorMsg.equals(expectedErrorMessageAME2_Compiled)) { 208 // Sparc and the other platforms behave differently here: 209 // Sparc throws the exception via SharedRuntime::handle_wrong_method_abstract(), 210 // x86, ppc and s390 via LinkResolver::runtime_resolve_virtual_method(). Thus, 211 // sparc misses the test case for LinkResolver::runtime_resolve_virtual_method(). 212 seenCompiled = true; 213 } else { 214 System.out.println("Expected: " + expectedErrorMessageAME2_Interpreted + "\n" + 215 "or: " + expectedErrorMessageAME2_Compiled + "\n" + 216 "but got: " + errorMsg); 217 throw new RuntimeException("Wrong error message of AbstractMethodError."); 218 } 219 } 220 } 221 if (!(seenInterpreted && seenCompiled)) { 222 if (seenInterpreted) { System.out.println("Saw interpreted message."); } 223 if (seenCompiled) { System.out.println("Saw compiled message."); } 224 throw new RuntimeException("Test did not produce wrong error messages for AbstractMethodError, " + 225 "but it did not test both cases (interpreted and compiled)."); 226 } 227 } 228 229 private static String expectedErrorMessageAME3_1 = 230 "Receiver class AME3_C does not define or inherit an implementation of the resolved method " + 231 "'void ma()' of class AME3_A. Selected method is 'abstract void AME3_B.ma()'."; 232 233 // Testing abstract class that extends a class that has an implementation. 234 // Loop so that method gets eventually compiled/osred. 235 public static void test_ame3_1() throws Exception { 236 AME3_A c = new AME3_C(); 237 238 try { 239 // Supposed to throw AME with verbose message. 240 c.ma(); 241 242 throw new RuntimeException("Expected AbstractMethodError was not thrown."); 243 } catch (AbstractMethodError e) { 244 String errorMsg = e.getMessage(); 245 246 // Check the message obtained. 247 if (errorMsg == null) { 248 throw new RuntimeException("Caught AbstractMethodError with empty message."); 249 } else if (errorMsg.equals(expectedErrorMessageAME3_1)) { 250 // Expected test case thrown via LinkResolver::runtime_resolve_virtual_method(). 251 System.out.println("Passed with message: " + errorMsg); 252 } else { 253 System.out.println("Expected: " + expectedErrorMessageAME3_1 + "\n" + 254 "but got: " + errorMsg); 255 throw new RuntimeException("Wrong error message of AbstractMethodError."); 256 } 257 } 258 } 259 260 private static String expectedErrorMessageAME3_2 = 261 "Receiver class AME3_C does not define or inherit an implementation of " + 262 "the resolved method 'abstract void ma()' of abstract class AME3_B."; 263 264 // Testing abstract class that extends a class that has an implementation. 265 // Loop so that method gets eventually compiled/osred. 266 public static void test_ame3_2() throws Exception { 267 AME3_C c = new AME3_C(); 268 269 try { 270 // Supposed to throw AME with verbose message. 271 c.ma(); 272 273 throw new RuntimeException("Expected AbstractMethodError was not thrown."); 274 } catch (AbstractMethodError e) { 275 String errorMsg = e.getMessage(); 276 277 // Check the message obtained. 278 if (errorMsg == null) { 279 throw new RuntimeException("Caught AbstractMethodError with empty message."); 280 } else if (errorMsg.equals(expectedErrorMessageAME3_2)) { 281 // Expected test case thrown via LinkResolver::runtime_resolve_virtual_method(). 282 System.out.println("Passed with message: " + errorMsg); 283 } else { 284 System.out.println("Expected: " + expectedErrorMessageAME3_2 + "\n" + 285 "but got: " + errorMsg); 286 throw new RuntimeException("Wrong error message of AbstractMethodError."); 287 } 288 } 289 } 290 291 private static String expectedErrorMessageAME4 = 292 "Missing implementation of resolved method 'abstract void ma()' of " + 293 "abstract class AME4_B."; 294 295 // Testing abstract class that extends a class that has an implementation. 296 public static void test_ame4() throws Exception { 297 AME4_C c = new AME4_C(); 298 AME4_D d = new AME4_D(); 299 AME4_E e = new AME4_E(); // Errorneous. 300 301 AME4_A a; 302 try { 303 // Test: calls errorneous e.ma() in the last iteration. 304 final int iterations = 10; 305 for (int i = 0; i < iterations; i++) { 306 a = e; 307 if (i % 2 == 0 && i < iterations - 1) { 308 a = c; 309 } 310 if (i % 2 == 1 && i < iterations - 1) { 311 a = d; 312 } 313 314 // AbstractMethodError gets thrown in the interpreter at: 315 // InterpreterGenerator::generate_abstract_entry 316 a.ma(); 317 } 318 319 throw new RuntimeException("Expected AbstractMethodError was not thrown."); 320 } catch (AbstractMethodError exc) { 321 System.out.println(); 322 String errorMsg = exc.getMessage(); 323 324 // Check the message obtained. 325 if (enableChecks && errorMsg == null) { 326 throw new RuntimeException("Caught AbstractMethodError with empty message."); 327 } else if (errorMsg.equals(expectedErrorMessageAME4)) { 328 // Expected test case. 329 System.out.println("Passed with message: " + errorMsg); 330 } else if (enableChecks) { 331 System.out.println("Expected: " + expectedErrorMessageAME4 + "\n" + 332 "but got: " + errorMsg); 333 throw new RuntimeException("Wrong error message of AbstractMethodError."); 334 } 335 } 336 } 337 338 private static String expectedErrorMessageAME5_VtableStub = 339 "Receiver class AME5_B does not define or inherit an implementation of the resolved method 'abstract void mc()' " + 340 "of abstract class AME5_A."; 341 342 // AbstractMethodErrors detected in vtable stubs. 343 // Note: How can we verify that we really stepped through the vtable stub? 344 // - Bimorphic inlining should not happen since we have no profiling data when 345 // we compile the method 346 // - As a result, an inline cache call should be generated 347 // - This inline cache call is patched into a real vtable call at the first 348 // re-resolve, which happens constantly during the first 10 iterations of the loop. 349 // => we should be fine! :-) 350 public static void test_ame5_compiled_vtable_stub() { 351 // Allocated the objects we need and call a valid method. 352 boolean caught_ame = false; 353 AME5_B b = new AME5_B(); 354 AME5_C c = new AME5_C(); 355 AME5_D d = new AME5_D(); 356 AME5_E e = new AME5_E(); 357 b.ma(); 358 c.ma(); 359 d.ma(); 360 e.ma(); 361 362 try { 363 final int iterations = 10; 364 // Test: calls b.c() in the last iteration. 365 for (int i = 0; i < iterations; i++) { 366 AME5_A a = b; 367 if (i % 3 == 0 && i < iterations - 1) { 368 a = c; 369 } 370 if (i % 3 == 1 && i < iterations - 1) { 371 a = d; 372 } 373 if (i % 3 == 2 && i < iterations - 1) { 374 a = e; 375 } 376 377 a.mc(); 378 } 379 System.out.println(); 380 } catch (AbstractMethodError exc) { 381 caught_ame = true; 382 System.out.println(); 383 String errorMsg = exc.getMessage(); 384 if (enableChecks && errorMsg == null) { 385 System.out.println(exc); 386 throw new RuntimeException("Empty error message of AbstractMethodError."); 387 } 388 if (enableChecks && 389 !errorMsg.equals(expectedErrorMessageAME5_VtableStub)) { 390 // Thrown via SharedRuntime::handle_wrong_method_abstract(). 391 System.out.println("Expected: " + expectedErrorMessageAME5_VtableStub + "\n" + 392 "but got: " + errorMsg); 393 System.out.println(exc); 394 throw new RuntimeException("Wrong error message of AbstractMethodError."); 395 } 396 if (enableChecks) { 397 System.out.println("Passed with message: " + errorMsg); 398 } 399 } catch (Throwable exc) { 400 401 throw exc; 402 } 403 404 // Check that we got the exception at some point. 405 if (enableChecks && !caught_ame) { 406 throw new RuntimeException("Expected AbstractMethodError was not thrown."); 407 } 408 } 409 410 private static String expectedErrorMessageAME6_ItableStub = 411 "Receiver class AME6_B does not define or inherit an implementation of the resolved" + 412 " method 'abstract void mc()' of interface AME6_A."; 413 414 // ------------------------------------------------------------------------- 415 // AbstractMethodErrors detected in itable stubs. 416 // Note: How can we verify that we really stepped through the itable stub? 417 // - Bimorphic inlining should not happen since we have no profiling data when 418 // we compile the method 419 // - As a result, an inline cache call should be generated 420 // - This inline cache call is patched into a real vtable call at the first 421 // re-resolve, which happens constantly during the first 10 iterations of the loop. 422 // => we should be fine! :-) 423 public static void test_ame6_compiled_itable_stub() { 424 // Allocated the objects we need and call a valid method. 425 boolean caught_ame = false; 426 AME6_B b = new AME6_B(); 427 AME6_C c = new AME6_C(); 428 AME6_D d = new AME6_D(); 429 AME6_E e = new AME6_E(); 430 b.ma(); 431 c.ma(); 432 d.ma(); 433 e.ma(); 434 435 try { 436 final int iterations = 10; 437 // Test: calls b.c() in the last iteration. 438 for (int i = 0; i < iterations; i++) { 439 AME6_A a = b; 440 if (i % 3 == 0 && i < iterations - 1) { 441 a = c; 442 } 443 if (i % 3 == 1 && i < iterations - 1) { 444 a = d; 445 } 446 if (i % 3 == 2 && i < iterations - 1) { 447 a = e; 448 } 449 a.mc(); 450 } 451 System.out.println(); 452 } catch (AbstractMethodError exc) { 453 caught_ame = true; 454 System.out.println(); 455 String errorMsg = exc.getMessage(); 456 if (enableChecks && errorMsg == null) { 457 System.out.println(exc); 458 throw new RuntimeException("Empty error message of AbstractMethodError."); 459 } 460 if (enableChecks && 461 !errorMsg.equals(expectedErrorMessageAME6_ItableStub)) { 462 // Thrown via LinkResolver::runtime_resolve_interface_method(). 463 System.out.println("Expected: " + expectedErrorMessageAME6_ItableStub + "\n" + 464 "but got: " + errorMsg); 465 System.out.println(exc); 466 throw new RuntimeException("Wrong error message of AbstractMethodError."); 467 } 468 if (enableChecks) { 469 System.out.println("Passed with message: " + errorMsg); 470 } 471 } catch (Throwable exc) { 472 throw exc; 473 } 474 475 // Check that we got the exception at some point. 476 if (enableChecks && !caught_ame) { 477 throw new RuntimeException("Expected AbstractMethodError was not thrown."); 478 } 479 } 480 481 482 public static void main(String[] args) throws Exception { 483 if (!setup_test()) { 484 return; 485 } 486 test_ame1(); 487 test_ame2(); 488 test_ame3_1(); 489 test_ame3_2(); 490 test_ame4(); 491 test_ame5_compiled_vtable_stub(); 492 test_ame6_compiled_itable_stub(); 493 } 494 } 495 496 // Helper classes to test abstract method error. 497 // 498 // Errorneous versions of these classes are implemented in java 499 // assembler. 500 501 502 // ------------------------------------------------------------------------- 503 // This error should be detected interpreted. 504 // 505 // Class hierachy: 506 // 507 // C // interface, defines aFunctionOfMyInterface() 508 // | 509 // A | // interface 510 // | | 511 // B | // abstract class, defines anAbstractMethod() 512 // \ / 513 // E // errorneous class implementation lacks methods C::aFunctionOfMyInterface() 514 // B::anAbstractMethod() 515 interface AME1_A { 516 517 public String firstFunctionOfMyInterface0(); 518 519 public String secondFunctionOfMyInterface0(); 520 } 521 522 abstract class AME1_B implements AME1_A { 523 524 abstract public String firstAbstractMethod(); 525 526 abstract public String secondAbstractMethod(); 527 528 abstract public String anAbstractMethod(); 529 } 530 531 interface AME1_C { 532 533 public String firstFunctionOfMyInterface(); 534 535 public String secondFunctionOfMyInterface(); 536 537 public String aFunctionOfMyInterface(); 538 } 539 540 class AME1_D extends AME1_B implements AME1_C { 541 542 public AME1_D() { 543 } 544 545 public String firstAbstractMethod() { 546 return this.getClass().getName(); 547 } 548 549 public String secondAbstractMethod() { 550 return this.getClass().getName(); 551 } 552 553 public String anAbstractMethod() { 554 return this.getClass().getName(); 555 } 556 557 public String firstFunctionOfMyInterface0() { 558 return this.getClass().getName(); 559 } 560 561 public String secondFunctionOfMyInterface0() { 562 return this.getClass().getName(); 563 } 564 565 public String firstFunctionOfMyInterface() { 566 return this.getClass().getName(); 567 } 568 569 public String secondFunctionOfMyInterface() { 570 return this.getClass().getName(); 571 } 572 573 public String aFunctionOfMyInterface() { 574 return this.getClass().getName(); 575 } 576 } 577 578 class AME1_E extends AME1_B implements AME1_C { 579 580 public AME1_E() { 581 } 582 583 public String firstAbstractMethod() { 584 return this.getClass().getName(); 585 } 586 587 public String secondAbstractMethod() { 588 return this.getClass().getName(); 589 } 590 591 // This method is missing in the .jasm implementation. 592 public String anAbstractMethod() { 593 return this.getClass().getName(); 594 } 595 596 public String firstFunctionOfMyInterface0() { 597 return this.getClass().getName(); 598 } 599 600 public String secondFunctionOfMyInterface0() { 601 return this.getClass().getName(); 602 } 603 604 public String firstFunctionOfMyInterface() { 605 return this.getClass().getName(); 606 } 607 608 public String secondFunctionOfMyInterface() { 609 return this.getClass().getName(); 610 } 611 612 // This method is missing in the .jasm implementation. 613 public String aFunctionOfMyInterface() { 614 return this.getClass().getName(); 615 } 616 } 617 618 // ------------------------------------------------------------------------- 619 // This error should be detected interpreted. 620 // 621 // Class hierachy: 622 // 623 // A // an interface declaring aFunctionOfMyInterface() 624 // | 625 // B // an abstract class 626 // | 627 // C // errorneous implementation lacks method A::aFunctionOfMyInterface() 628 // 629 interface AME2_A { 630 public void aFunctionOfMyInterface(); 631 } 632 633 abstract class AME2_B implements AME2_A { 634 abstract public void fun2(); 635 } 636 637 class ImplementsAllFunctions extends AME2_B { 638 639 public ImplementsAllFunctions() {} 640 641 public void fun2() { 642 //System.out.print("You called public void ImplementsAllFunctions::fun2().\n"); 643 } 644 645 public void aFunctionOfMyInterface() { 646 //System.out.print("You called public void ImplementsAllFunctions::aFunctionOfMyInterface()\n"); 647 } 648 } 649 650 class AME2_C extends AME2_B { 651 652 public AME2_C() {} 653 654 public void fun2() { 655 //System.out.print("You called public void AME2_C::fun2().\n"); 656 } 657 658 // This method is missing in the .jasm implementation. 659 public void aFunctionOfMyInterface() { 660 //System.out.print("You called public void AME2_C::aFunctionOfMyInterface()\n"); 661 } 662 } 663 664 // ----------------------------------------------------------------------- 665 // Test AbstractMethod error shadowing existing implementation. 666 // 667 // Class hierachy: 668 // 669 // A // a class implementing m() 670 // | 671 // B // an abstract class defining m() abstract 672 // | 673 // C // an errorneous class lacking an implementation of m() 674 // 675 class AME3_A { 676 public void ma() { 677 System.out.print("A.ma() "); 678 } 679 } 680 681 abstract class AME3_B extends AME3_A { 682 public abstract void ma(); 683 } 684 685 class AME3_C extends AME3_B { 686 // This method is missing in the .jasm implementation. 687 public void ma() { 688 System.out.print("C.ma() "); 689 } 690 } 691 692 // ----------------------------------------------------------------------- 693 // Test AbstractMethod error shadowing existing implementation. In 694 // this test there are several subclasses of the abstract class. 695 // 696 // Class hierachy: 697 // 698 // A // A: a class implementing ma() 699 // | 700 // B // B: an abstract class defining ma() abstract 701 // / | \ 702 // C D E // E: an errorneous class lacking an implementation of ma() 703 // 704 class AME4_A { 705 public void ma() { 706 System.out.print("A.ma() "); 707 } 708 } 709 710 abstract class AME4_B extends AME4_A { 711 public abstract void ma(); 712 } 713 714 class AME4_C extends AME4_B { 715 public void ma() { 716 System.out.print("C.ma() "); 717 } 718 } 719 720 class AME4_D extends AME4_B { 721 public void ma() { 722 System.out.print("D.ma() "); 723 } 724 } 725 726 class AME4_E extends AME4_B { 727 // This method is missing in the .jasm implementation. 728 public void ma() { 729 System.out.print("E.ma() "); 730 } 731 } 732 733 // ------------------------------------------------------------------------- 734 // This error should be detected while processing the vtable stub. 735 // 736 // Class hierachy: 737 // 738 // A__ // abstract 739 // /|\ \ 740 // C D E \ 741 // B // Bad class, missing method implementation. 742 // 743 // Test: 744 // - Call D.mc() / E.mc() / F.mc() several times to force real vtable call constrution 745 // - Call errorneous B.mc() in the end to raise the AbstraceMethodError 746 747 abstract class AME5_A { 748 public abstract void ma(); 749 public abstract void mb(); 750 public abstract void mc(); 751 } 752 753 class AME5_B extends AME5_A { 754 public void ma() { 755 System.out.print("B.ma() "); 756 } 757 758 public void mb() { 759 System.out.print("B.mb() "); 760 } 761 762 // This method is missing in the .jasm implementation. 763 public void mc() { 764 System.out.print("B.mc() "); 765 } 766 } 767 768 class AME5_C extends AME5_A { 769 public void ma() { 770 System.out.print("C.ma() "); 771 } 772 773 public void mb() { 774 System.out.print("C.mb() "); 775 } 776 777 public void mc() { 778 System.out.print("C.mc() "); 779 } 780 } 781 782 class AME5_D extends AME5_A { 783 public void ma() { 784 System.out.print("D.ma() "); 785 } 786 787 public void mb() { 788 System.out.print("D.mb() "); 789 } 790 791 public void mc() { 792 System.out.print("D.mc() "); 793 } 794 } 795 796 class AME5_E extends AME5_A { 797 public void ma() { 798 System.out.print("E.ma() "); 799 } 800 801 public void mb() { 802 System.out.print("E.mb() "); 803 } 804 805 public void mc() { 806 System.out.print("E.mc() "); 807 } 808 } 809 810 //------------------------------------------------------------------------- 811 // Test AbstractMethod error detected while processing 812 // the itable stub. 813 // 814 // Class hierachy: 815 // 816 // A__ (interface) 817 // /|\ \ 818 // C D E \ 819 // B (bad class, missing method) 820 // 821 // Test: 822 // - Call D.mc() / E.mc() / F.mc() several times to force real itable call constrution 823 // - Call errorneous B.mc() in the end to raise the AbstraceMethodError 824 825 interface AME6_A { 826 abstract void ma(); 827 abstract void mb(); 828 abstract void mc(); 829 } 830 831 class AME6_B implements AME6_A { 832 public void ma() { 833 System.out.print("B.ma() "); 834 } 835 836 public void mb() { 837 System.out.print("B.mb() "); 838 } 839 840 // This method is missing in the .jasm implementation. 841 public void mc() { 842 System.out.print("B.mc() "); 843 } 844 } 845 846 class AME6_C implements AME6_A { 847 public void ma() { 848 System.out.print("C.ma() "); 849 } 850 851 public void mb() { 852 System.out.print("C.mb() "); 853 } 854 855 public void mc() { 856 System.out.print("C.mc() "); 857 } 858 } 859 860 class AME6_D implements AME6_A { 861 public void ma() { 862 System.out.print("D.ma() "); 863 } 864 865 public void mb() { 866 System.out.print("D.mb() "); 867 } 868 869 public void mc() { 870 System.out.print("D.mc() "); 871 } 872 } 873 874 class AME6_E implements AME6_A { 875 public void ma() { 876 System.out.print("E.ma() "); 877 } 878 879 public void mb() { 880 System.out.print("E.mb() "); 881 } 882 883 public void mc() { 884 System.out.print("E.mc() "); 885 } 886 }