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