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:");
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)) {
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 }
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
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();
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();
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 }
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() ");
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 }
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 }
|
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:");
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)) {
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 }
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
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();
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();
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 }
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() ");
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 }
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 }
|