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