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