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