1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2018 SAP SE. All rights reserved.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 /**
  26  * @test
  27  * @summary Check that the verbose message of the AME is printed correctly.
  28  * @requires !(os.arch=="aarch64" | os.arch=="arm")
  29  * @library /test/lib /
  30  * @build sun.hotspot.WhiteBox
  31  * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
  32  * @compile AbstractMethodErrorTest.java
  33  * @compile AME1_E.jasm AME2_C.jasm AME3_C.jasm AME4_E.jasm AME5_B.jasm AME6_B.jasm
  34  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
  35  *                   -XX:-BackgroundCompilation -XX:-Inline
  36  *                   -XX:CompileCommand=exclude,AbstractMethodErrorTest::test_ame1
  37  *                   AbstractMethodErrorTest
  38  */
  39 
  40 import sun.hotspot.WhiteBox;
  41 import compiler.whitebox.CompilerWhiteBoxTest;
  42 import java.lang.reflect.Method;
  43 
  44 // This test assembles an 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 //      A     C     // interfaces
 514 //      |     |
 515 //      B     |     // abstract class
 516 //       \   /
 517 //         E        // errorneous class implementation lacks method C::aFunctionOfMyInterface
 518 //
 519 interface AME1_A {
 520 
 521     public String firstFunctionOfMyInterface0();
 522 
 523     public String secondFunctionOfMyInterface0();
 524 }
 525 
 526 abstract class AME1_B implements AME1_A {
 527 
 528     abstract public String firstAbstractMethod();
 529 
 530     abstract public String secondAbstractMethod();
 531 
 532     abstract public String anAbstractMethod();
 533 }
 534 
 535 interface AME1_C {
 536 
 537     public String firstFunctionOfMyInterface();
 538 
 539     public String secondFunctionOfMyInterface();
 540 
 541     public String aFunctionOfMyInterface();
 542 }
 543 
 544 class AME1_D extends AME1_B implements AME1_C {
 545 
 546     public AME1_D() {
 547     }
 548 
 549     public String firstAbstractMethod() {
 550         return this.getClass().getName();
 551     }
 552 
 553     public String secondAbstractMethod() {
 554         return this.getClass().getName();
 555     }
 556 
 557     public String anAbstractMethod() {
 558         return this.getClass().getName();
 559     }
 560 
 561     public String firstFunctionOfMyInterface0() {
 562         return this.getClass().getName();
 563     }
 564 
 565     public String secondFunctionOfMyInterface0() {
 566         return this.getClass().getName();
 567     }
 568 
 569     public String firstFunctionOfMyInterface() {
 570         return this.getClass().getName();
 571     }
 572 
 573     public String secondFunctionOfMyInterface() {
 574         return this.getClass().getName();
 575     }
 576 
 577     public String aFunctionOfMyInterface() {
 578         return this.getClass().getName();
 579     }
 580 }
 581 
 582 class AME1_E extends AME1_B implements AME1_C {
 583 
 584     public AME1_E() {
 585     }
 586 
 587     public String firstAbstractMethod() {
 588         return this.getClass().getName();
 589     }
 590 
 591     public String secondAbstractMethod() {
 592         return this.getClass().getName();
 593     }
 594 
 595     // This method is missing in the .jasm implementation.
 596     public String anAbstractMethod() {
 597         return this.getClass().getName();
 598     }
 599 
 600     public String firstFunctionOfMyInterface0() {
 601         return this.getClass().getName();
 602     }
 603 
 604     public String secondFunctionOfMyInterface0() {
 605         return this.getClass().getName();
 606     }
 607 
 608     public String firstFunctionOfMyInterface() {
 609         return this.getClass().getName();
 610     }
 611 
 612     public String secondFunctionOfMyInterface() {
 613         return this.getClass().getName();
 614     }
 615 
 616     // This method is missing in the .jasm implementation.
 617     public String aFunctionOfMyInterface() {
 618         return this.getClass().getName();
 619     }
 620 }
 621 
 622 // -------------------------------------------------------------------------
 623 // This error should be detected interpreted.
 624 //
 625 // Class hierachy:
 626 //
 627 //      A   // an interface declaring aFunctionOfMyInterface()
 628 //      |
 629 //      B   // an abstract class
 630 //      |
 631 //      C   // errorneous implementation lacks method A::aFunctionOfMyInterface()
 632 //
 633 interface AME2_A {
 634     public void aFunctionOfMyInterface();
 635 }
 636 
 637 abstract class AME2_B implements AME2_A {
 638     abstract public void fun2();
 639 }
 640 
 641 class ImplementsAllFunctions extends AME2_B {
 642 
 643     public ImplementsAllFunctions() {}
 644 
 645     public void fun2() {
 646         //System.out.print("You called public void ImplementsAllFunctions::fun2().\n");
 647     }
 648 
 649     public void aFunctionOfMyInterface() {
 650         //System.out.print("You called public void ImplementsAllFunctions::aFunctionOfMyInterface()\n");
 651     }
 652 }
 653 
 654 class AME2_C extends AME2_B {
 655 
 656     public AME2_C() {}
 657 
 658     public void fun2() {
 659         //System.out.print("You called public void AME2_C::fun2().\n");
 660     }
 661 
 662     // This method is missing in the .jasm implementation.
 663     public void aFunctionOfMyInterface() {
 664         //System.out.print("You called public void AME2_C::aFunctionOfMyInterface()\n");
 665     }
 666 }
 667 
 668 // -----------------------------------------------------------------------
 669 // Test AbstractMethod error shadowing existing implementation.
 670 //
 671 // Class hierachy:
 672 //
 673 //           A           // a class implementing m()
 674 //           |
 675 //           B           // an abstract class defining m() abstract
 676 //           |
 677 //           C           // an errorneous class lacking an implementation of m()
 678 //
 679 class AME3_A {
 680     public void ma() {
 681         System.out.print("A.ma() ");
 682     }
 683 }
 684 
 685 abstract class AME3_B extends AME3_A {
 686     public abstract void ma();
 687 }
 688 
 689 class AME3_C extends AME3_B {
 690     // This method is missing in the .jasm implementation.
 691     public void ma() {
 692         System.out.print("C.ma() ");
 693     }
 694 }
 695 
 696 // -----------------------------------------------------------------------
 697 // Test AbstractMethod error shadowing existing implementation. In
 698 // this test there are several subclasses of the abstract class.
 699 //
 700 // Class hierachy:
 701 //
 702 //           A           // A: a class implementing ma()
 703 //           |
 704 //           B           // B: an abstract class defining ma() abstract
 705 //        /  | \
 706 //       C   D  E        // E: an errorneous class lacking an implementation of ma()
 707 //
 708 class AME4_A {
 709     public void ma() {
 710         System.out.print("A.ma() ");
 711     }
 712 }
 713 
 714 abstract class AME4_B extends AME4_A {
 715     public abstract void ma();
 716 }
 717 
 718 class AME4_C extends AME4_B {
 719     public void ma() {
 720         System.out.print("C.ma() ");
 721     }
 722 }
 723 
 724 class AME4_D extends AME4_B {
 725     public void ma() {
 726         System.out.print("D.ma() ");
 727     }
 728 }
 729 
 730 class AME4_E extends AME4_B {
 731     // This method is missing in the .jasm implementation.
 732     public void ma() {
 733         System.out.print("E.ma() ");
 734     }
 735 }
 736 
 737 // -------------------------------------------------------------------------
 738 // This error should be detected while processing the vtable stub.
 739 //
 740 // Class hierachy:
 741 //
 742 //              A__     // abstract
 743 //             /|\ \
 744 //            C D E \
 745 //                   B  // Bad class, missing method implementation.
 746 //
 747 // Test:
 748 // - Call D.mc() / E.mc() / F.mc() several times to force real vtable call constrution
 749 // - Call errorneous B.mc() in the end to raise the AbstraceMethodError
 750 
 751 abstract class AME5_A {
 752     abstract void ma();
 753     abstract void mb();
 754     abstract void mc();
 755 }
 756 
 757 class AME5_B extends AME5_A {
 758     void ma() {
 759         System.out.print("B.ma() ");
 760     }
 761 
 762     void mb() {
 763         System.out.print("B.mb() ");
 764     }
 765 
 766     // This method is missing in the .jasm implementation.
 767     void mc() {
 768         System.out.print("B.mc() ");
 769     }
 770 }
 771 
 772 class AME5_C extends AME5_A {
 773     void ma() {
 774         System.out.print("C.ma() ");
 775     }
 776 
 777     void mb() {
 778         System.out.print("C.mb() ");
 779     }
 780 
 781     void mc() {
 782         System.out.print("C.mc() ");
 783     }
 784 }
 785 
 786 class AME5_D extends AME5_A {
 787     void ma() {
 788         System.out.print("D.ma() ");
 789     }
 790 
 791     void mb() {
 792         System.out.print("D.mb() ");
 793     }
 794 
 795     void mc() {
 796         System.out.print("D.mc() ");
 797     }
 798 }
 799 
 800 class AME5_E extends AME5_A {
 801     void ma() {
 802        System.out.print("E.ma() ");
 803    }
 804 
 805    void mb() {
 806        System.out.print("E.mb() ");
 807    }
 808 
 809    void mc() {
 810        System.out.print("E.mc() ");
 811    }
 812 }
 813 
 814 //-------------------------------------------------------------------------
 815 // Test AbstractMethod error detected while processing
 816 // the itable stub.
 817 //
 818 // Class hierachy:
 819 //
 820 //           A__   (interface)
 821 //          /|\ \
 822 //         C D E \
 823 //                B (bad class, missing method)
 824 //
 825 // Test:
 826 // - Call D.mc() / E.mc() / F.mc() several times to force real itable call constrution
 827 // - Call errorneous B.mc() in the end to raise the AbstraceMethodError
 828 
 829 interface AME6_A {
 830     abstract void ma();
 831     abstract void mb();
 832     abstract void mc();
 833 }
 834 
 835 class AME6_B implements AME6_A {
 836     public void ma() {
 837         System.out.print("B.ma() ");
 838     }
 839 
 840     public void mb() {
 841         System.out.print("B.mb() ");
 842     }
 843 
 844     // This method is missing in the .jasm implementation.
 845     public void mc() {
 846         System.out.print("B.mc() ");
 847     }
 848 }
 849 
 850 class AME6_C implements AME6_A {
 851     public void ma() {
 852         System.out.print("C.ma() ");
 853     }
 854 
 855     public void mb() {
 856         System.out.print("C.mb() ");
 857     }
 858 
 859     public void mc() {
 860         System.out.print("C.mc() ");
 861     }
 862 }
 863 
 864 class AME6_D implements AME6_A {
 865     public void ma() {
 866         System.out.print("D.ma() ");
 867     }
 868 
 869     public void mb() {
 870         System.out.print("D.mb() ");
 871     }
 872 
 873     public void mc() {
 874         System.out.print("D.mc() ");
 875     }
 876 }
 877 
 878 class AME6_E implements AME6_A {
 879     public void ma() {
 880         System.out.print("E.ma() ");
 881     }
 882 
 883     public void mb() {
 884         System.out.print("E.mb() ");
 885     }
 886 
 887     public void mc() {
 888         System.out.print("E.mc() ");
 889     }
 890 }