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