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.UseJVMCICompiler != 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 }