8197405: Improve messages of AbstractMethodErrors and IncompatibleClassChangeErrors.
authorgoetz
Thu, 08 Feb 2018 09:23:49 +0100
changeset 49368 2ed1c37df3a5
parent 49366 f95ef5511e1f
child 49369 62dd99c3a6f9
8197405: Improve messages of AbstractMethodErrors and IncompatibleClassChangeErrors. Reviewed-by: coleenp, dholmes, mdoerr, njian
src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp
src/hotspot/cpu/aarch64/templateTable_aarch64.cpp
src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp
src/hotspot/cpu/arm/vtableStubs_arm.cpp
src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp
src/hotspot/cpu/ppc/templateTable_ppc_64.cpp
src/hotspot/cpu/s390/sharedRuntime_s390.cpp
src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp
src/hotspot/cpu/s390/templateTable_s390.cpp
src/hotspot/cpu/sparc/templateInterpreterGenerator_sparc.cpp
src/hotspot/cpu/sparc/templateTable_sparc.cpp
src/hotspot/cpu/sparc/vtableStubs_sparc.cpp
src/hotspot/cpu/x86/stubGenerator_x86_64.cpp
src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp
src/hotspot/cpu/x86/templateTable_x86.cpp
src/hotspot/cpu/x86/vtableStubs_x86_32.cpp
src/hotspot/cpu/x86/vtableStubs_x86_64.cpp
src/hotspot/share/interpreter/bytecodeInterpreter.cpp
src/hotspot/share/interpreter/interpreterRuntime.cpp
src/hotspot/share/interpreter/interpreterRuntime.hpp
src/hotspot/share/interpreter/linkResolver.cpp
src/hotspot/share/interpreter/linkResolver.hpp
src/hotspot/share/oops/klass.cpp
src/hotspot/share/oops/klass.hpp
src/hotspot/share/runtime/sharedRuntime.cpp
test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AME1_E.jasm
test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AME2_C.jasm
test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AME3_C.jasm
test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AME4_E.jasm
test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AME5_B.jasm
test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AME6_B.jasm
test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AbstractMethodErrorTest.java
test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/ICC_B.jasm
test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/ImplementsSomeInterfaces.jasm
test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/IncompatibleClassChangeErrorTest.java
--- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -293,7 +293,8 @@
 
   // throw exception
   __ call_VM(noreg, CAST_FROM_FN_PTR(address,
-                             InterpreterRuntime::throw_AbstractMethodError));
+                                     InterpreterRuntime::throw_AbstractMethodErrorWithMethod),
+                                     rmethod);
   // the call_VM checks for exception, so we should never return here.
   __ should_not_reach_here();
 
--- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -3440,6 +3440,8 @@
 
   Label no_such_interface, no_such_method;
 
+  // Preserve method for throw_AbstractMethodErrorVerbose.
+  __ mov(r16, rmethod);
   // Receiver subtype check against REFC.
   // Superklass in r0. Subklass in r3. Blows rscratch2, r13
   __ lookup_interface_method(// inputs: rec. class, interface, itable index
@@ -3460,8 +3462,10 @@
   __ subw(rmethod, rmethod, Method::itable_index_max);
   __ negw(rmethod, rmethod);
 
+  // Preserve recvKlass for throw_AbstractMethodErrorVerbose.
+  __ mov(rlocals, r3);
   __ lookup_interface_method(// inputs: rec. class, interface, itable index
-                             r3, r0, rmethod,
+                             rlocals, r0, rmethod,
                              // outputs: method, scan temp. reg
                              rmethod, r13,
                              no_such_interface);
@@ -3490,7 +3494,8 @@
   // throw exception
   __ restore_bcp();      // bcp must be correct for exception handler   (was destroyed)
   __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
-  __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
+  // Pass arguments for generating a verbose error message.
+  __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodErrorVerbose), r3, r16);
   // the call_VM checks for exception, so we should never return here.
   __ should_not_reach_here();
 
@@ -3498,8 +3503,9 @@
   // throw exception
   __ restore_bcp();      // bcp must be correct for exception handler   (was destroyed)
   __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
+  // Pass arguments for generating a verbose error message.
   __ call_VM(noreg, CAST_FROM_FN_PTR(address,
-                   InterpreterRuntime::throw_IncompatibleClassChangeError));
+                   InterpreterRuntime::throw_IncompatibleClassChangeErrorVerbose), r3, r0);
   // the call_VM checks for exception, so we should never return here.
   __ should_not_reach_here();
   return;
--- a/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -201,7 +201,12 @@
   __ br(rscratch1);
 
   __ bind(L_no_such_interface);
-  __ far_jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
+  // Handle IncompatibleClassChangeError in itable stubs.
+  // More detailed error message.
+  // We force resolving of the call site by jumping to the "handle
+  // wrong method" stub, and so let the interpreter runtime do all the
+  // dirty work.
+  __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
 
   __ flush();
 
--- a/src/hotspot/cpu/arm/vtableStubs_arm.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/cpu/arm/vtableStubs_arm.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -158,8 +158,13 @@
 
   __ bind(L_no_such_interface);
 
-  assert(StubRoutines::throw_IncompatibleClassChangeError_entry() != NULL, "check initialization order");
-  __ jump(StubRoutines::throw_IncompatibleClassChangeError_entry(), relocInfo::runtime_call_type, Rtemp);
+  // Handle IncompatibleClassChangeError in itable stubs.
+  // More detailed error message.
+  // We force resolving of the call site by jumping to the "handle
+  // wrong method" stub, and so let the interpreter runtime do all the
+  // dirty work.
+  assert(SharedRuntime::get_handle_wrong_method_stub() != NULL, "check initialization order");
+  __ jump(SharedRuntime::get_handle_wrong_method_stub(), relocInfo::runtime_call_type, Rtemp);
 
   masm->flush();
 
--- a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -452,8 +452,8 @@
 
   // This is not a leaf but we have a JavaFrameAnchor now and we will
   // check (create) exceptions afterward so this is ok.
-  __ call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError),
-                  R16_thread);
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodErrorWithMethod),
+                  R16_thread, R19_method);
 
   // Pop the C frame and restore LR.
   __ pop_frame();
--- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -3688,11 +3688,15 @@
 
   // Vtable entry was NULL => Throw abstract method error.
   __ bind(Lthrow_ame);
-  call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
+  // Pass arguments for generating a verbose error message.
+  call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodErrorVerbose),
+          Rrecv_klass, Rmethod);
 
   // Interface was not found => Throw incompatible class change error.
   __ bind(L_no_such_interface);
-  call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError));
+  // Pass arguments for generating a verbose error message.
+  call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeErrorVerbose),
+          Rrecv_klass, Rinterface_klass);
   DEBUG_ONLY( __ should_not_reach_here(); )
 
   // Special case of invokeinterface called for virtual method of
--- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -2105,7 +2105,7 @@
   // blocking or unlocking.
   // An OOP result (handle) is done specially in the slow-path code.
   //--------------------------------------------------------------------
-  switch (ret_type) {  //GLGLGL
+  switch (ret_type) {
     case T_VOID:    break;         // Nothing to do!
     case T_FLOAT:   break;         // Got it where we want it (unless slow-path)
     case T_DOUBLE:  break;         // Got it where we want it (unless slow-path)
--- a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -458,7 +458,8 @@
   __ save_return_pc();       // Save Z_R14.
   __ push_frame_abi160(0);   // Without new frame the RT call could overwrite the saved Z_R14.
 
-  __ call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError), Z_thread);
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodErrorWithMethod),
+                  Z_thread, Z_method);
 
   __ pop_frame();
   __ restore_return_pc();    // Restore Z_R14.
@@ -686,7 +687,7 @@
   return entry;
 }
 
-address TemplateInterpreterGenerator::generate_deopt_entry_for (TosState state,
+address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state,
                                                                int step,
                                                                address continuation) {
   address entry = __ pc();
--- a/src/hotspot/cpu/s390/templateTable_s390.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/cpu/s390/templateTable_s390.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -3742,8 +3742,12 @@
   // Throw exception.
   __ restore_bcp();      // Bcp must be correct for exception handler   (was destroyed).
   __ restore_locals();   // Make sure locals pointer is correct as well (was destroyed).
+  // Pass arguments for generating a verbose error message.
+  __ z_lgr(Z_tmp_1, method); // Prevent register clash.
   __ call_VM(noreg,
-             CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
+             CAST_FROM_FN_PTR(address,
+                              InterpreterRuntime::throw_AbstractMethodErrorVerbose),
+                              klass, Z_tmp_1);
   // The call_VM checks for exception, so we should never return here.
   __ should_not_reach_here();
 
@@ -3752,8 +3756,11 @@
   // Throw exception.
   __ restore_bcp();      // Bcp must be correct for exception handler   (was destroyed).
   __ restore_locals();   // Make sure locals pointer is correct as well (was destroyed).
+  // Pass arguments for generating a verbose error message.
   __ call_VM(noreg,
-             CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError));
+             CAST_FROM_FN_PTR(address,
+                              InterpreterRuntime::throw_IncompatibleClassChangeErrorVerbose),
+                              klass, interface);
   // The call_VM checks for exception, so we should never return here.
   __ should_not_reach_here();
 
--- a/src/hotspot/cpu/sparc/templateInterpreterGenerator_sparc.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/cpu/sparc/templateInterpreterGenerator_sparc.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -191,7 +191,7 @@
   address entry = __ pc();
   // abstract method entry
   // throw exception
-  __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
+  __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodErrorWithMethod), G5_method);
   // the call_VM checks for exception, so we should never return here.
   __ should_not_reach_here();
   return entry;
--- a/src/hotspot/cpu/sparc/templateTable_sparc.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/cpu/sparc/templateTable_sparc.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -3137,8 +3137,10 @@
   __ sub(Rindex, Method::itable_index_max, Rindex);
   __ neg(Rindex);
 
+  // Preserve O2_Klass for throw_AbstractMethodErrorVerbose
+  __ mov(O2_Klass, O4);
   __ lookup_interface_method(// inputs: rec. class, interface, itable index
-                             O2_Klass, Rinterface, Rindex,
+                             O4, Rinterface, Rindex,
                              // outputs: method, scan temp reg, temp reg
                              G5_method, Rscratch, Rtemp,
                              L_no_such_interface);
@@ -3147,7 +3149,9 @@
   {
     Label ok;
     __ br_notnull_short(G5_method, Assembler::pt, ok);
-    call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
+    // Pass arguments for generating a verbose error message.
+    call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodErrorVerbose),
+            O2_Klass, Rmethod);
     __ should_not_reach_here();
     __ bind(ok);
   }
@@ -3160,7 +3164,9 @@
   __ call_from_interpreter(Rcall, Gargs, Rret);
 
   __ bind(L_no_such_interface);
-  call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError));
+  // Pass arguments for generating a verbose error message.
+  call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeErrorVerbose),
+          O2_Klass, Rinterface);
   __ should_not_reach_here();
 }
 
@@ -3536,7 +3542,7 @@
 void TemplateTable::_breakpoint() {
 
    // Note: We get here even if we are single stepping..
-   // jbug inists on setting breakpoints at every bytecode
+   // jbug insists on setting breakpoints at every bytecode
    // even if we are in single step mode.
 
    transition(vtos, vtos);
--- a/src/hotspot/cpu/sparc/vtableStubs_sparc.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/cpu/sparc/vtableStubs_sparc.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -212,7 +212,12 @@
   __ delayed()->nop();
 
   __ bind(L_no_such_interface);
-  AddressLiteral icce(StubRoutines::throw_IncompatibleClassChangeError_entry());
+  // Handle IncompatibleClassChangeError in itable stubs.
+  // More detailed error message.
+  // We force resolving of the call site by jumping to the "handle
+  // wrong method" stub, and so let the interpreter runtime do all the
+  // dirty work.
+  AddressLiteral icce(SharedRuntime::get_handle_wrong_method_stub());
   __ jump_to(icce, G3_scratch);
   __ delayed()->restore();
 
--- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -4425,7 +4425,7 @@
    *    c_rarg0   - x address
    *    c_rarg1   - x length
    *    c_rarg2   - y address
-   *    c_rarg3   - y lenth
+   *    c_rarg3   - y length
    * not Win64
    *    c_rarg4   - z address
    *    c_rarg5   - z length
--- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -1354,7 +1354,7 @@
   __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
 
   // throw exception
-  __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
+  __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodErrorWithMethod), rbx);
   // the call_VM checks for exception, so we should never return here.
   __ should_not_reach_here();
 
--- a/src/hotspot/cpu/x86/templateTable_x86.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/cpu/x86/templateTable_x86.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -3872,6 +3872,8 @@
 
   Label no_such_interface, no_such_method;
 
+  // Preserve method for throw_AbstractMethodErrorVerbose.
+  __ mov(rcx, rbx);
   // Receiver subtype check against REFC.
   // Superklass in rax. Subklass in rdx. Blows rcx, rdi.
   __ lookup_interface_method(// inputs: rec. class, interface, itable index
@@ -3893,8 +3895,10 @@
   __ subl(rbx, Method::itable_index_max);
   __ negl(rbx);
 
+  // Preserve recvKlass for throw_AbstractMethodErrorVerbose.
+  __ mov(rlocals, rdx);
   __ lookup_interface_method(// inputs: rec. class, interface, itable index
-                             rdx, rax, rbx,
+                             rlocals, rax, rbx,
                              // outputs: method, scan temp. reg
                              rbx, rbcp,
                              no_such_interface);
@@ -3926,8 +3930,19 @@
   __ pop(rbx);           // pop return address (pushed by prepare_invoke)
   __ restore_bcp();      // rbcp must be correct for exception handler   (was destroyed)
   __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
-  __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
-  // the call_VM checks for exception, so we should never return here.
+  // Pass arguments for generating a verbose error message.
+#ifdef _LP64
+  Register recvKlass = c_rarg1;
+  Register method    = c_rarg2;
+  if (recvKlass != rdx) { __ movq(recvKlass, rdx); }
+  if (method != rcx)    { __ movq(method, rcx);    }
+#else
+  Register recvKlass = rdx;
+  Register method    = rcx;
+#endif
+  __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodErrorVerbose),
+             recvKlass, method);
+  // The call_VM checks for exception, so we should never return here.
   __ should_not_reach_here();
 
   __ bind(no_such_interface);
@@ -3935,8 +3950,10 @@
   __ pop(rbx);           // pop return address (pushed by prepare_invoke)
   __ restore_bcp();      // rbcp must be correct for exception handler   (was destroyed)
   __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
-  __ call_VM(noreg, CAST_FROM_FN_PTR(address,
-                   InterpreterRuntime::throw_IncompatibleClassChangeError));
+  // Pass arguments for generating a verbose error message.
+  LP64_ONLY( if (recvKlass != rdx) { __ movq(recvKlass, rdx); } )
+  __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeErrorVerbose),
+             recvKlass, rax);
   // the call_VM checks for exception, so we should never return here.
   __ should_not_reach_here();
 }
--- a/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -212,7 +212,12 @@
   __ jmp(Address(method, Method::from_compiled_offset()));
 
   __ bind(L_no_such_interface);
-  __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
+  // Handle IncompatibleClassChangeError in itable stubs.
+  // More detailed error message.
+  // We force resolving of the call site by jumping to the "handle
+  // wrong method" stub, and so let the interpreter runtime do all the
+  // dirty work.
+  __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
 
   __ flush();
 
--- a/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -182,10 +182,10 @@
   const Register method = rbx;
   __ load_klass(recv_klass_reg, j_rarg0);   // restore recv_klass_reg
   __ lookup_interface_method(// inputs: rec. class, interface, itable index
-                       recv_klass_reg, holder_klass_reg, itable_index,
-                       // outputs: method, scan temp. reg
-                       method, temp_reg,
-                       L_no_such_interface);
+                             recv_klass_reg, holder_klass_reg, itable_index,
+                             // outputs: method, scan temp. reg
+                             method, temp_reg,
+                             L_no_such_interface);
 
   // If we take a trap while this arg is on the stack we will not
   // be able to walk the stack properly. This is not an issue except
@@ -213,7 +213,12 @@
   __ jmp(Address(method, Method::from_compiled_offset()));
 
   __ bind(L_no_such_interface);
-  __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
+  // Handle IncompatibleClassChangeError in itable stubs.
+  // More detailed error message.
+  // We force resolving of the call site by jumping to the "handle
+  // wrong method" stub, and so let the interpreter runtime do all the
+  // dirty work.
+  __ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
 
   __ flush();
 
--- a/src/hotspot/share/interpreter/bytecodeInterpreter.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/share/interpreter/bytecodeInterpreter.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -2589,17 +2589,19 @@
           if (ki->interface_klass() == iclass) break;
         }
         // If the interface isn't found, this class doesn't implement this
-        // interface.  The link resolver checks this but only for the first
+        // interface. The link resolver checks this but only for the first
         // time this interface is called.
         if (i == int2->itable_length()) {
-          VM_JAVA_ERROR(vmSymbols::java_lang_IncompatibleClassChangeError(), "", note_no_trap);
+          CALL_VM(InterpreterRuntime::throw_IncompatibleClassChangeErrorVerbose(THREAD, rcvr->klass(), iclass),
+                  handle_exception);
         }
         int mindex = interface_method->itable_index();
 
         itableMethodEntry* im = ki->first_method_entry(rcvr->klass());
         callee = im[mindex].method();
         if (callee == NULL) {
-          VM_JAVA_ERROR(vmSymbols::java_lang_AbstractMethodError(), "", note_no_trap);
+          CALL_VM(InterpreterRuntime::throw_AbstractMethodErrorVerbose(THREAD, rcvr->klass(), interface_method),
+                  handle_exception);
         }
 
         // Profile virtual call.
--- a/src/hotspot/share/interpreter/interpreterRuntime.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -487,8 +487,8 @@
       ResourceMark rm(thread);
       stringStream tempst;
       tempst.print("interpreter method <%s>\n"
-                   " at bci %d for thread " INTPTR_FORMAT,
-                   h_method->print_value_string(), current_bci, p2i(thread));
+                   " at bci %d for thread " INTPTR_FORMAT " (%s)",
+                   h_method->print_value_string(), current_bci, p2i(thread), thread->name());
       Exceptions::log_exception(h_exception, tempst);
     }
 // Don't go paging in something which won't be used.
@@ -582,11 +582,45 @@
   THROW(vmSymbols::java_lang_AbstractMethodError());
 IRT_END
 
+// This method is called from the "abstract_entry" of the interpreter.
+// At that point, the arguments have already been removed from the stack
+// and therefore we don't have the receiver object at our fingertips. (Though,
+// on some platforms the receiver still resides in a register...). Thus,
+// we have no choice but print an error message not containing the receiver
+// type.
+IRT_ENTRY(void, InterpreterRuntime::throw_AbstractMethodErrorWithMethod(JavaThread* thread,
+                                                                        Method* missingMethod))
+  ResourceMark rm(thread);
+  assert(missingMethod != NULL, "sanity");
+  methodHandle m(thread, missingMethod);
+  LinkResolver::throw_abstract_method_error(m, THREAD);
+IRT_END
+
+IRT_ENTRY(void, InterpreterRuntime::throw_AbstractMethodErrorVerbose(JavaThread* thread,
+                                                                     Klass* recvKlass,
+                                                                     Method* missingMethod))
+  ResourceMark rm(thread);
+  methodHandle mh = methodHandle(thread, missingMethod);
+  LinkResolver::throw_abstract_method_error(mh, recvKlass, THREAD);
+IRT_END
+
 
 IRT_ENTRY(void, InterpreterRuntime::throw_IncompatibleClassChangeError(JavaThread* thread))
   THROW(vmSymbols::java_lang_IncompatibleClassChangeError());
 IRT_END
 
+IRT_ENTRY(void, InterpreterRuntime::throw_IncompatibleClassChangeErrorVerbose(JavaThread* thread,
+                                                                              Klass* recvKlass,
+                                                                              Klass* interfaceKlass))
+  ResourceMark rm(thread);
+  char buf[1000];
+  buf[0] = '\0';
+  jio_snprintf(buf, sizeof(buf),
+               "Class %s does not implement the requested interface %s",
+               recvKlass ? recvKlass->external_name() : "NULL",
+               interfaceKlass ? interfaceKlass->external_name() : "NULL");
+  THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+IRT_END
 
 //------------------------------------------------------------------------------------------------------------------------
 // Fields
--- a/src/hotspot/share/interpreter/interpreterRuntime.hpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/share/interpreter/interpreterRuntime.hpp	Thu Feb 08 09:23:49 2018 +0100
@@ -118,7 +118,15 @@
 
   // Exceptions thrown by the interpreter
   static void    throw_AbstractMethodError(JavaThread* thread);
+  static void    throw_AbstractMethodErrorWithMethod(JavaThread* thread, Method* oop);
+  static void    throw_AbstractMethodErrorVerbose(JavaThread* thread,
+                                                  Klass* recvKlass,
+                                                  Method* missingMethod);
+
   static void    throw_IncompatibleClassChangeError(JavaThread* thread);
+  static void    throw_IncompatibleClassChangeErrorVerbose(JavaThread* thread,
+                                                           Klass* resc,
+                                                           Klass* interfaceKlass);
   static void    throw_StackOverflowError(JavaThread* thread);
   static void    throw_delayed_StackOverflowError(JavaThread* thread);
   static void    throw_ArrayIndexOutOfBoundsException(JavaThread* thread, char* name, jint index);
--- a/src/hotspot/share/interpreter/linkResolver.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/share/interpreter/linkResolver.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -1344,8 +1344,7 @@
 
   // do lookup based on receiver klass using the vtable index
   if (resolved_method->method_holder()->is_interface()) { // default or miranda method
-    vtable_index = vtable_index_of_interface_method(resolved_klass,
-                           resolved_method);
+    vtable_index = vtable_index_of_interface_method(resolved_klass, resolved_method);
     assert(vtable_index >= 0 , "we should have valid vtable index at this point");
 
     selected_method = methodHandle(THREAD, recv_klass->method_at_vtable(vtable_index));
@@ -1355,7 +1354,7 @@
     assert(!resolved_method->has_itable_index(), "");
     vtable_index = resolved_method->vtable_index();
     // We could get a negative vtable_index for final methods,
-    // because as an optimization they are they are never put in the vtable,
+    // because as an optimization they are never put in the vtable,
     // unless they override an existing method.
     // If we do get a negative, it means the resolved method is the the selected
     // method, and it can never be changed by an override.
@@ -1369,20 +1368,13 @@
 
   // check if method exists
   if (selected_method.is_null()) {
-    ResourceMark rm(THREAD);
-    THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
-              Method::name_and_sig_as_C_string(resolved_klass,
-                                               resolved_method->name(),
-                                               resolved_method->signature()));
+    throw_abstract_method_error(resolved_method, recv_klass, CHECK);
   }
 
   // check if abstract
   if (check_null_and_abstract && selected_method->is_abstract()) {
-    ResourceMark rm(THREAD);
-    THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
-              Method::name_and_sig_as_C_string(resolved_klass,
-                                               selected_method->name(),
-                                               selected_method->signature()));
+    // Pass arguments for generating a verbose error message.
+    throw_abstract_method_error(resolved_method, selected_method, recv_klass, CHECK);
   }
 
   if (log_develop_is_enabled(Trace, vtables)) {
@@ -1438,53 +1430,46 @@
   // do lookup based on receiver klass
   // This search must match the linktime preparation search for itable initialization
   // to correctly enforce loader constraints for interface method inheritance
-  methodHandle sel_method = lookup_instance_method_in_klasses(recv_klass,
+  methodHandle selected_method = lookup_instance_method_in_klasses(recv_klass,
                                                   resolved_method->name(),
                                                   resolved_method->signature(), CHECK);
-  if (sel_method.is_null() && !check_null_and_abstract) {
+  if (selected_method.is_null() && !check_null_and_abstract) {
     // In theory this is a harmless placeholder value, but
     // in practice leaving in null affects the nsk default method tests.
     // This needs further study.
-    sel_method = resolved_method;
+    selected_method = resolved_method;
   }
   // check if method exists
-  if (sel_method.is_null()) {
-    ResourceMark rm(THREAD);
-    THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
-                   Method::name_and_sig_as_C_string(recv_klass,
-                                                    resolved_method->name(),
-                                                    resolved_method->signature()));
+  if (selected_method.is_null()) {
+    // Pass arguments for generating a verbose error message.
+    throw_abstract_method_error(resolved_method, recv_klass, CHECK);
   }
   // check access
-  // Throw Illegal Access Error if sel_method is not public.
-  if (!sel_method->is_public()) {
+  // Throw Illegal Access Error if selected_method is not public.
+  if (!selected_method->is_public()) {
     ResourceMark rm(THREAD);
     THROW_MSG(vmSymbols::java_lang_IllegalAccessError(),
               Method::name_and_sig_as_C_string(recv_klass,
-                                               sel_method->name(),
-                                               sel_method->signature()));
+                                               selected_method->name(),
+                                               selected_method->signature()));
   }
   // check if abstract
-  if (check_null_and_abstract && sel_method->is_abstract()) {
-    ResourceMark rm(THREAD);
-    THROW_MSG(vmSymbols::java_lang_AbstractMethodError(),
-              Method::name_and_sig_as_C_string(recv_klass,
-                                               sel_method->name(),
-                                               sel_method->signature()));
+  if (check_null_and_abstract && selected_method->is_abstract()) {
+    throw_abstract_method_error(resolved_method, selected_method, recv_klass, CHECK);
   }
 
   if (log_develop_is_enabled(Trace, itables)) {
     trace_method_resolution("invokeinterface selected method: receiver-class:",
-                            recv_klass, resolved_klass, sel_method, true);
+                            recv_klass, resolved_klass, selected_method, true);
   }
   // setup result
   if (!resolved_method->has_itable_index()) {
     int vtable_index = resolved_method->vtable_index();
-    assert(vtable_index == sel_method->vtable_index(), "sanity check");
-    result.set_virtual(resolved_klass, recv_klass, resolved_method, sel_method, vtable_index, CHECK);
+    assert(vtable_index == selected_method->vtable_index(), "sanity check");
+    result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK);
   } else {
     int itable_index = resolved_method()->itable_index();
-    result.set_interface(resolved_klass, recv_klass, resolved_method, sel_method, itable_index, CHECK);
+    result.set_interface(resolved_klass, recv_klass, resolved_method, selected_method, itable_index, CHECK);
   }
 }
 
@@ -1774,3 +1759,38 @@
   result.set_handle(resolved_method, resolved_appendix, resolved_method_type, THREAD);
   Exceptions::wrap_dynamic_exception(CHECK);
 }
+
+// Selected method is abstract.
+void LinkResolver::throw_abstract_method_error(const methodHandle& resolved_method,
+                                               const methodHandle& selected_method,
+                                               Klass *recv_klass, TRAPS) {
+  Klass *resolved_klass = resolved_method->method_holder();
+  ResourceMark rm(THREAD);
+  stringStream ss;
+
+  if (recv_klass != NULL) {
+    ss.print("Receiver class %s does not define or inherit an "
+             "implementation of the",
+             recv_klass->external_name());
+  } else {
+    ss.print("Missing implementation of");
+  }
+
+  assert(resolved_method.not_null(), "Sanity");
+  ss.print(" resolved method %s%s%s%s of %s %s.",
+           resolved_method->is_abstract() ? "abstract " : "",
+           resolved_method->is_private()  ? "private "  : "",
+           resolved_method->name()->as_C_string(),
+           resolved_method->signature()->as_C_string(),
+           resolved_klass->external_kind(),
+           resolved_klass->external_name());
+
+  if (selected_method.not_null() && !(resolved_method == selected_method)) {
+    ss.print(" Selected method is %s%s%s.",
+             selected_method->is_abstract() ? "abstract " : "",
+             selected_method->is_private()  ? "private "  : "",
+             selected_method->name_and_sig_as_C_string());
+  }
+
+  THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), ss.as_string());
+}
--- a/src/hotspot/share/interpreter/linkResolver.hpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/share/interpreter/linkResolver.hpp	Thu Feb 08 09:23:49 2018 +0100
@@ -347,5 +347,19 @@
   static void resolve_invoke(CallInfo& result, Handle& recv,
                              const methodHandle& attached_method,
                              Bytecodes::Code byte, TRAPS);
+
+ public:
+  // Only resolved method known.
+  static void throw_abstract_method_error(const methodHandle& resolved_method, TRAPS) {
+    throw_abstract_method_error(resolved_method, NULL, NULL, CHECK);
+  }
+  // Resolved method and receiver klass know.
+  static void throw_abstract_method_error(const methodHandle& resolved_method, Klass *recv_klass, TRAPS) {
+    throw_abstract_method_error(resolved_method, NULL, recv_klass, CHECK);
+  }
+  // Selected method is abstract.
+  static void throw_abstract_method_error(const methodHandle& resolved_method,
+                                          const methodHandle& selected_method,
+                                          Klass *recv_klass, TRAPS);
 };
 #endif // SHARE_VM_INTERPRETER_LINKRESOLVER_HPP
--- a/src/hotspot/share/oops/klass.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/share/oops/klass.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -636,12 +636,17 @@
   return name()->as_klass_external_name();
 }
 
-
 const char* Klass::signature_name() const {
   if (name() == NULL)  return "<unknown>";
   return name()->as_C_string();
 }
 
+const char* Klass::external_kind() const {
+  if (is_interface()) return "interface";
+  if (is_abstract()) return "abstract class";
+  return "class";
+}
+
 // Unless overridden, modifier_flags is 0.
 jint Klass::compute_modifier_flags(TRAPS) const {
   return 0;
--- a/src/hotspot/share/oops/klass.hpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/share/oops/klass.hpp	Thu Feb 08 09:23:49 2018 +0100
@@ -546,6 +546,9 @@
 
   const char* class_loader_and_module_name() const;
 
+  // Returns "interface", "abstract class" or "class".
+  const char* external_kind() const;
+
   // type testing operations
 #ifdef ASSERT
  protected:
--- a/src/hotspot/share/runtime/sharedRuntime.cpp	Fri Mar 09 12:03:20 2018 -0500
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp	Thu Feb 08 09:23:49 2018 +0100
@@ -839,9 +839,15 @@
           if (vt_stub->is_abstract_method_error(pc)) {
             assert(!vt_stub->is_vtable_stub(), "should never see AbstractMethodErrors from vtable-type VtableStubs");
             Events::log_exception(thread, "AbstractMethodError at " INTPTR_FORMAT, p2i(pc));
-            return StubRoutines::throw_AbstractMethodError_entry();
+            // Instead of throwing the abstract method error here directly, we re-resolve
+            // and will throw the AbstractMethodError during resolve. As a result, we'll
+            // get a more detailed error message.
+            return SharedRuntime::get_handle_wrong_method_stub();
           } else {
             Events::log_exception(thread, "NullPointerException at vtable entry " INTPTR_FORMAT, p2i(pc));
+            // Assert that the signal comes from the expected location in stub code.
+            assert(vt_stub->is_null_pointer_exception(pc),
+                   "obtained signal from unexpected location in stub code");
             return StubRoutines::throw_NullPointerException_at_call_entry();
           }
         } else {
@@ -1454,7 +1460,29 @@
 
 // Handle abstract method call
 JRT_BLOCK_ENTRY(address, SharedRuntime::handle_wrong_method_abstract(JavaThread* thread))
-  return StubRoutines::throw_AbstractMethodError_entry();
+  // Verbose error message for AbstractMethodError.
+  // Get the called method from the invoke bytecode.
+  vframeStream vfst(thread, true);
+  assert(!vfst.at_end(), "Java frame must exist");
+  methodHandle caller(vfst.method());
+  Bytecode_invoke invoke(caller, vfst.bci());
+  DEBUG_ONLY( invoke.verify(); )
+
+  // Find the compiled caller frame.
+  RegisterMap reg_map(thread);
+  frame stubFrame = thread->last_frame();
+  assert(stubFrame.is_runtime_frame(), "must be");
+  frame callerFrame = stubFrame.sender(&reg_map);
+  assert(callerFrame.is_compiled_frame(), "must be");
+
+  // Install exception and return forward entry.
+  JRT_BLOCK
+    methodHandle callee = invoke.static_target(thread);
+    assert(!callee.is_null() && invoke.has_receiver(), "or we should not be here");
+    oop recv = callerFrame.retrieve_receiver(&reg_map);
+    LinkResolver::throw_abstract_method_error(callee, recv->klass(), thread);
+  JRT_BLOCK_END
+  return StubRoutines::forward_exception_entry();
 JRT_END
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AME1_E.jasm	Thu Feb 08 09:23:49 2018 +0100
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 SAP SE. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* Method aFunctionOfMyInterface:"()Ljava/lang/String;" is missing in this implementation to cause error. */
+
+class AME1_E extends AME1_B implements AME1_C {
+
+    public Method "<init>":"()V"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokespecial Method AME1_B."<init>":"()V";
+        return;
+    }
+
+    public Method firstAbstractMethod:"()Ljava/lang/String;"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokevirtual Method java/lang/Object.getClass:"()Ljava/lang/Class;";
+        invokevirtual Method java/lang/Class.getName:"()Ljava/lang/String;";
+        areturn;
+    }
+
+    public Method secondAbstractMethod:"()Ljava/lang/String;"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokevirtual Method java/lang/Object.getClass:"()Ljava/lang/Class;";
+        invokevirtual Method java/lang/Class.getName:"()Ljava/lang/String;";
+        areturn;
+    }
+    
+    /* Missing to cause error.
+    public Method anAbstractMethod:"()Ljava/lang/String;"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokevirtual Method java/lang/Object.getClass:"()Ljava/lang/Class;";
+        invokevirtual Method java/lang/Class.getName:"()Ljava/lang/String;";
+        areturn;
+    }
+    */
+
+    public Method firstFunctionOfMyInterface0:"()Ljava/lang/String;"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokevirtual Method java/lang/Object.getClass:"()Ljava/lang/Class;";
+        invokevirtual Method java/lang/Class.getName:"()Ljava/lang/String;";
+        areturn;
+    }
+
+    public Method secondFunctionOfMyInterface0:"()Ljava/lang/String;"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokevirtual Method java/lang/Object.getClass:"()Ljava/lang/Class;";
+        invokevirtual Method java/lang/Class.getName:"()Ljava/lang/String;";
+        areturn;
+    }
+
+    public Method firstFunctionOfMyInterface:"()Ljava/lang/String;"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokevirtual Method java/lang/Object.getClass:"()Ljava/lang/Class;";
+        invokevirtual Method java/lang/Class.getName:"()Ljava/lang/String;";
+        areturn;
+    }
+
+    public Method secondFunctionOfMyInterface:"()Ljava/lang/String;"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokevirtual Method java/lang/Object.getClass:"()Ljava/lang/Class;";
+        invokevirtual Method java/lang/Class.getName:"()Ljava/lang/String;";
+        areturn;
+    }
+
+    /* Missing to cause error.
+    public Method aFunctionOfMyInterface:"()Ljava/lang/String;"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokevirtual Method java/lang/Object.getClass:"()Ljava/lang/Class;";
+        invokevirtual Method java/lang/Class.getName:"()Ljava/lang/String;";
+        areturn;
+    }
+    */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AME2_C.jasm	Thu Feb 08 09:23:49 2018 +0100
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 SAP SE. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* Method aFunctionOfMyInterface() is missing in this implementation to cause error. */
+
+class AME2_C extends AME2_B {
+
+    public Method "<init>":"()V"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokespecial Method AME2_B."<init>":"()V";
+        return;
+    }
+
+    public Method fun2:"()V"
+        stack 0 locals 1
+    {
+        return;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AME3_C.jasm	Thu Feb 08 09:23:49 2018 +0100
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 SAP SE. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* Method ma() is missing in this implementation to cause error. */
+
+class AME3_C extends AME3_B {
+    public Method "<init>":"()V"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokespecial Method AME3_B."<init>":()V;
+        return;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AME4_E.jasm	Thu Feb 08 09:23:49 2018 +0100
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 SAP SE. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/* Method ma() is missing in this implementation to cause error. */
+
+class AME4_E extends AME4_B {
+    public Method "<init>":"()V"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokespecial Method AME4_B."<init>":()V;
+        return;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AME5_B.jasm	Thu Feb 08 09:23:49 2018 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 SAP SE. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* Method mc() is missing in this implementation to cause error. */
+
+class AME5_B extends AME5_A {
+    public Method "<init>":"()V"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokespecial Method AME5_A."<init>":()V;
+        return;
+    }
+
+    public Method ma:"()V"
+        stack 2 locals 1
+    {
+        getstatic     Field java/lang/System.out:"Ljava/io/PrintStream;";
+        ldc           String "B.ma() ";
+        invokevirtual Method java/io/PrintStream.print:"(Ljava/lang/String;)V";
+        return;
+    }
+
+    public Method mb:"()V"
+        stack 2 locals 1
+    {
+        getstatic     Field java/lang/System.out:"Ljava/io/PrintStream;";
+        ldc           String "B.mb() ";
+        invokevirtual Method java/io/PrintStream.print:"(Ljava/lang/String;)V";
+        return;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AME6_B.jasm	Thu Feb 08 09:23:49 2018 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 SAP SE. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* Method mc() is missing in this implementation to cause error. */
+
+class AME6_B implements AME6_A {
+    public Method "<init>":"()V"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokespecial Method java/lang/Object."<init>":"()V";
+        return;
+    }
+
+    public Method ma:"()V"
+        stack 2 locals 1
+    {
+        getstatic     Field java/lang/System.out:"Ljava/io/PrintStream;";
+        ldc           String "B.ma() ";
+        invokevirtual Method java/io/PrintStream.print:"(Ljava/lang/String;)V";
+        return;
+    }
+
+    public Method mb:"()V"
+        stack 2 locals 1
+    {
+        getstatic     Field java/lang/System.out:"Ljava/io/PrintStream;";
+        ldc           String "B.mb() ";
+        invokevirtual Method java/io/PrintStream.print:"(Ljava/lang/String;)V";
+        return;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AbstractMethodErrorTest.java	Thu Feb 08 09:23:49 2018 +0100
@@ -0,0 +1,892 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 SAP SE. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Check that the verbose message of the AME is printed correctly.
+ * @requires !(os.arch=="arm")
+ * @library /test/lib /
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @compile AbstractMethodErrorTest.java
+ * @compile AME1_E.jasm AME2_C.jasm AME3_C.jasm AME4_E.jasm AME5_B.jasm AME6_B.jasm
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:-BackgroundCompilation -XX:-Inline
+ *                   -XX:CompileCommand=exclude,AbstractMethodErrorTest::test_ame1
+ *                   AbstractMethodErrorTest
+ */
+
+import sun.hotspot.WhiteBox;
+import compiler.whitebox.CompilerWhiteBoxTest;
+import java.lang.reflect.Method;
+
+// This test assembles an errorneous installation of classes.
+// First, compile the test by @compile. This results in a legal set
+// of classes.
+// Then, with jasm, generate incompatible classes that overwrite
+// the class files in the build directory.
+// Last, call the real test throwing an AbstractMethodError and
+// check the message generated.
+public class AbstractMethodErrorTest {
+
+    private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+
+    private static boolean enableChecks = true;
+
+    public static void setup_test() {
+        // Assure all exceptions are loaded.
+        new AbstractMethodError();
+        new IncompatibleClassChangeError();
+
+        enableChecks = false;
+        // Warmup
+        System.out.println("warmup:");
+        test_ame5_compiled_vtable_stub();
+        test_ame6_compiled_itable_stub();
+        enableChecks = true;
+
+        // Compile
+        try {
+            Method method = AbstractMethodErrorTest.class.getMethod("test_ame5_compiled_vtable_stub");
+            WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
+            if (!WHITE_BOX.isMethodCompiled(method)) {
+                throw new RuntimeException(method.getName() + " is not compiled");
+            }
+            method = AbstractMethodErrorTest.class.getMethod("test_ame6_compiled_itable_stub");
+            WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
+            if (!WHITE_BOX.isMethodCompiled(method)) {
+                throw new RuntimeException(method.getName() + " is not compiled");
+            }
+            method = AME5_C.class.getMethod("c");
+            WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
+            if (!WHITE_BOX.isMethodCompiled(method)) {
+                throw new RuntimeException("AME5_C." + method.getName() + " is not compiled");
+            }
+            method = AME5_D.class.getMethod("c");
+            WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
+            if (!WHITE_BOX.isMethodCompiled(method)) {
+                throw new RuntimeException("AME5_D." + method.getName() + " is not compiled");
+            }
+            method = AME5_E.class.getMethod("c");
+            WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
+            if (!WHITE_BOX.isMethodCompiled(method)) {
+                throw new RuntimeException("AME5_E." + method.getName() + " is not compiled");
+            }
+            method = AME6_C.class.getMethod("c");
+            WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
+            if (!WHITE_BOX.isMethodCompiled(method)) {
+                throw new RuntimeException("AME6_C." + method.getName() + " is not compiled");
+            }
+            method = AME6_D.class.getMethod("c");
+            WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
+            if (!WHITE_BOX.isMethodCompiled(method)) {
+                throw new RuntimeException("AME6_D." + method.getName() + " is not compiled");
+            }
+            method = AME6_E.class.getMethod("c");
+            WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
+            if (!WHITE_BOX.isMethodCompiled(method)) {
+                throw new RuntimeException("AME6_E." + method.getName() + " is not compiled");
+            }
+        } catch (NoSuchMethodException e) { }
+    }
+
+    private static String expectedErrorMessageAME1_1 =
+        "Missing implementation of resolved method abstract " +
+        "anAbstractMethod()Ljava/lang/String; of abstract class AME1_B.";
+    private static String expectedErrorMessageAME1_2 =
+        "Receiver class AME1_E does not define or inherit an implementation of the " +
+        "resolved method abstract aFunctionOfMyInterface()Ljava/lang/String; of " +
+        "interface AME1_C.";
+
+    public static void test_ame1() {
+        AME1_B objectAbstract = new AME1_D();
+        AME1_C objectInterface = new AME1_D();
+        objectInterface.secondFunctionOfMyInterface();
+        objectAbstract.anAbstractMethod();
+        objectInterface.aFunctionOfMyInterface();
+
+        try {
+            objectAbstract = new AME1_E();
+            // AbstractMethodError gets thrown in the interpreter at:
+            // InterpreterGenerator::generate_abstract_entry
+            objectAbstract.anAbstractMethod();
+            throw new RuntimeException("Expected AbstractRuntimeError was not thrown.");
+        } catch (AbstractMethodError e) {
+            String errorMsg = e.getMessage();
+            if (errorMsg == null) {
+                throw new RuntimeException("Caught AbstractMethodError with empty message.");
+            } else if (!errorMsg.equals(expectedErrorMessageAME1_1)) {
+                System.out.println("Expected: " + expectedErrorMessageAME1_1 + "\n" +
+                                   "but got:  " + errorMsg);
+                throw new RuntimeException("Wrong error message of AbstractMethodError.");
+            }
+        } catch (RuntimeException e) {
+            throw e;
+        } catch (Throwable e) {
+            throw new RuntimeException("Caught unexpected exception: " + e);
+        }
+
+        try {
+            objectInterface = new AME1_E();
+            // AbstractMethodError gets thrown in:
+            // TemplateTable::invokeinterface or C-Interpreter loop
+            objectInterface.aFunctionOfMyInterface();
+            throw new RuntimeException("Expected AbstractRuntimeError was not thrown.");
+        } catch (AbstractMethodError e) {
+            String errorMsg = e.getMessage();
+            if (errorMsg == null) {
+                throw new RuntimeException("Caught AbstractMethodError with empty message.");
+            } else if (!errorMsg.equals(expectedErrorMessageAME1_2)) {
+                // Thrown via InterpreterRuntime::throw_AbstractMethodErrorVerbose().
+                System.out.println("Expected: " + expectedErrorMessageAME1_2 + "\n" +
+                                   "but got:  " + errorMsg);
+                throw new RuntimeException("Wrong error message of AbstractMethodError.");
+            }
+        } catch (Throwable e) {
+            throw new RuntimeException("Caught unexpected exception: " + e);
+        }
+    }
+
+    private static String expectedErrorMessageAME2_Interpreted =
+        "Missing implementation of resolved method abstract " +
+        "aFunctionOfMyInterface()V of interface AME2_A.";
+    private static String expectedErrorMessageAME2_Compiled =
+        "Receiver class AME2_C does not define or inherit an implementation of the resolved method " +
+        "abstract aFunctionOfMyInterface()V of interface AME2_A.";
+
+    public AbstractMethodErrorTest() throws InstantiationException, IllegalAccessException {
+        try {
+            AME2_B myAbstract = new ImplementsAllFunctions();
+            myAbstract.fun2();
+            myAbstract.aFunctionOfMyInterface();
+
+            // AME2_C does not implement the method
+            // aFunctionOfMyInterface(). Expected runtime behavior is
+            // throwing an AbstractMethodError.
+            // The error will be thrown via throw_AbstractMethodErrorWithMethod()
+            // if the template interpreter calls an abstract method by
+            // entering the abstract method entry.
+            myAbstract = new AME2_C();
+            myAbstract.fun2();
+            myAbstract.aFunctionOfMyInterface();
+        } catch (SecurityException e) {
+            e.printStackTrace();
+        }
+    }
+
+    // Loop so that method gets eventually compiled/osred.
+    public static void test_ame2() throws Exception {
+        boolean seenInterpreted = false;
+        boolean seenCompiled = false;
+
+        // Loop to test both, the interpreted and the compiled case.
+        for (int i = 0; i < 10000 && !(seenInterpreted && seenCompiled); ++i) {
+            try {
+                // Supposed to throw AME with verbose message.
+                new AbstractMethodErrorTest();
+
+                throw new RuntimeException("Expected AbstractMethodError was not thrown.");
+            } catch (AbstractMethodError e) {
+                String errorMsg = e.getMessage();
+
+                // Check the message obtained.
+                if (errorMsg == null) {
+                    throw new RuntimeException("Caught AbstractMethodError with empty message.");
+                } else if (errorMsg.equals(expectedErrorMessageAME2_Interpreted)) {
+                    seenInterpreted = true;
+                } else if (errorMsg.equals(expectedErrorMessageAME2_Compiled)) {
+                    // Sparc and the other platforms behave differently here:
+                    // Sparc throws the exception via SharedRuntime::handle_wrong_method_abstract(),
+                    // x86, ppc and s390 via LinkResolver::runtime_resolve_virtual_method(). Thus,
+                    // sparc misses the test case for LinkResolver::runtime_resolve_virtual_method().
+                    seenCompiled = true;
+                } else {
+                    System.out.println("Expected: " + expectedErrorMessageAME2_Interpreted + "\n" +
+                                       "or:       " + expectedErrorMessageAME2_Compiled + "\n" +
+                                       "but got:  " + errorMsg);
+                    throw new RuntimeException("Wrong error message of AbstractMethodError.");
+                }
+            }
+        }
+        if (!(seenInterpreted && seenCompiled)) {
+            if (seenInterpreted) { System.out.println("Saw interpreted message."); }
+            if (seenCompiled)    { System.out.println("Saw compiled message."); }
+            throw new RuntimeException("Test did not produce wrong error messages for AbstractMethodError, " +
+                                       "but it did not test both cases (interpreted and compiled).");
+        }
+    }
+
+    private static String expectedErrorMessageAME3_1 =
+        "Receiver class AME3_C does not define or inherit an implementation of the resolved method " +
+        "ma()V of class AME3_A. Selected method is abstract AME3_B.ma()V.";
+
+    // Testing abstract class that extends a class that has an implementation.
+    // Loop so that method gets eventually compiled/osred.
+    public static void test_ame3_1() throws Exception {
+        AME3_A c = new AME3_C();
+
+        try {
+            // Supposed to throw AME with verbose message.
+            c.ma();
+
+            throw new RuntimeException("Expected AbstractMethodError was not thrown.");
+        } catch (AbstractMethodError e) {
+            String errorMsg = e.getMessage();
+
+            // Check the message obtained.
+            if (errorMsg == null) {
+                throw new RuntimeException("Caught AbstractMethodError with empty message.");
+            } else if (errorMsg.equals(expectedErrorMessageAME3_1)) {
+                // Expected test case thrown via LinkResolver::runtime_resolve_virtual_method().
+            } else {
+                System.out.println("Expected: " + expectedErrorMessageAME3_1 + "\n" +
+                                   "but got:  " + errorMsg);
+                throw new RuntimeException("Wrong error message of AbstractMethodError.");
+            }
+        }
+    }
+
+    private static String expectedErrorMessageAME3_2 =
+        "Receiver class AME3_C does not define or inherit an implementation of " +
+        "the resolved method abstract ma()V of abstract class AME3_B.";
+
+    // Testing abstract class that extends a class that has an implementation.
+    // Loop so that method gets eventually compiled/osred.
+    public static void test_ame3_2() throws Exception {
+        AME3_C c = new AME3_C();
+
+        try {
+            // Supposed to throw AME with verbose message.
+            c.ma();
+
+            throw new RuntimeException("Expected AbstractMethodError was not thrown.");
+        } catch (AbstractMethodError e) {
+            String errorMsg = e.getMessage();
+
+            // Check the message obtained.
+            if (errorMsg == null) {
+                throw new RuntimeException("Caught AbstractMethodError with empty message.");
+            } else if (errorMsg.equals(expectedErrorMessageAME3_2)) {
+                // Expected test case thrown via LinkResolver::runtime_resolve_virtual_method().
+            } else {
+                System.out.println("Expected: " + expectedErrorMessageAME3_2 + "\n" +
+                                   "but got:  " + errorMsg);
+                throw new RuntimeException("Wrong error message of AbstractMethodError.");
+            }
+        }
+    }
+
+    private static String expectedErrorMessageAME4 =
+        "Missing implementation of resolved method abstract ma()V of " +
+        "abstract class AME4_B.";
+
+    // Testing abstract class that extends a class that has an implementation.
+    public static void test_ame4() throws Exception {
+        AME4_C c = new AME4_C();
+        AME4_D d = new AME4_D();
+        AME4_E e = new AME4_E();  // Errorneous.
+
+        AME4_A a;
+        try {
+            // Test: calls errorneous e.ma() in the last iteration.
+            final int iterations = 10;
+            for (int i = 0; i < iterations; i++) {
+                a = e;
+                if (i % 2 == 0 && i < iterations - 1) {
+                    a = c;
+                }
+                if (i % 2 == 1 && i < iterations - 1) {
+                    a = d;
+                }
+
+                // AbstractMethodError gets thrown in the interpreter at:
+                // InterpreterGenerator::generate_abstract_entry
+                a.ma();
+            }
+
+            throw new RuntimeException("Expected AbstractMethodError was not thrown.");
+        } catch (AbstractMethodError exc) {
+            System.out.println();
+            String errorMsg = exc.getMessage();
+
+                // Check the message obtained.
+            if (enableChecks && errorMsg == null) {
+                throw new RuntimeException("Caught AbstractMethodError with empty message.");
+            } else if (errorMsg.equals(expectedErrorMessageAME4)) {
+                // Expected test case.
+            } else if (enableChecks) {
+                System.out.println("Expected: " + expectedErrorMessageAME4 + "\n" +
+                                   "but got:  " + errorMsg);
+                throw new RuntimeException("Wrong error message of AbstractMethodError.");
+            }
+        }
+    }
+
+    private static String expectedErrorMessageAME5_VtableStub =
+        "Receiver class AME5_B does not define or inherit an implementation of the resolved method abstract mc()V " +
+        "of abstract class AME5_A.";
+
+    // AbstractMethodErrors detected in vtable stubs.
+    // Note: How can we verify that we really stepped through the vtable stub?
+    // - Bimorphic inlining should not happen since we have no profiling data when
+    //   we compile the method
+    // - As a result, an inline cache call should be generated
+    // - This inline cache call is patched into a real vtable call at the first
+    //   re-resolve, which happens constantly during the first 10 iterations of the loop.
+    // => we should be fine! :-)
+    public static void test_ame5_compiled_vtable_stub() {
+        // Allocated the objects we need and call a valid method.
+        boolean caught_ame = false;
+        AME5_B b = new AME5_B();
+        AME5_C c = new AME5_C();
+        AME5_D d = new AME5_D();
+        AME5_E e = new AME5_E();
+        b.ma();
+        c.ma();
+        d.ma();
+        e.ma();
+
+        try {
+            final int iterations = 10;
+            // Test: calls b.c() in the last iteration.
+            for (int i = 0; i < iterations; i++) {
+                AME5_A a = b;
+                if (i % 3 == 0 && i < iterations - 1) {
+                    a = c;
+                }
+                if (i % 3 == 1 && i < iterations - 1) {
+                    a = d;
+                }
+                if (i % 3 == 2 && i < iterations - 1) {
+                    a = e;
+                }
+
+              a.mc();
+            }
+            System.out.println();
+        } catch (AbstractMethodError exc) {
+            caught_ame = true;
+            System.out.println();
+            String errorMsg = exc.getMessage();
+            if (enableChecks && errorMsg == null) {
+                System.out.println(exc);
+                throw new RuntimeException("Empty error message of AbstractMethodError.");
+            }
+            if (enableChecks &&
+                !errorMsg.equals(expectedErrorMessageAME5_VtableStub)) {
+                // Thrown via SharedRuntime::handle_wrong_method_abstract().
+                System.out.println("Expected: " + expectedErrorMessageAME5_VtableStub + "\n" +
+                                   "but got:  " + errorMsg);
+                System.out.println(exc);
+                throw new RuntimeException("Wrong error message of AbstractMethodError.");
+            }
+            if (enableChecks) {
+                System.out.println("Passed with message: " + errorMsg);
+            }
+        } catch (Throwable exc) {
+
+        throw exc;
+        }
+
+        // Check that we got the exception at some point.
+        if (enableChecks && !caught_ame) {
+            throw new RuntimeException("Expected AbstractMethodError was not thrown.");
+        }
+    }
+
+    private static String expectedErrorMessageAME6_ItableStub =
+        "Receiver class AME6_B does not define or inherit an implementation of the resolved" +
+        " method abstract mc()V of interface AME6_A.";
+
+    // -------------------------------------------------------------------------
+    // AbstractMethodErrors detected in itable stubs.
+    // Note: How can we verify that we really stepped through the itable stub?
+    // - Bimorphic inlining should not happen since we have no profiling data when
+    //   we compile the method
+    // - As a result, an inline cache call should be generated
+    // - This inline cache call is patched into a real vtable call at the first
+    //   re-resolve, which happens constantly during the first 10 iterations of the loop.
+    // => we should be fine! :-)
+    public static void test_ame6_compiled_itable_stub() {
+        // Allocated the objects we need and call a valid method.
+        boolean caught_ame = false;
+        AME6_B b = new AME6_B();
+        AME6_C c = new AME6_C();
+        AME6_D d = new AME6_D();
+        AME6_E e = new AME6_E();
+        b.ma();
+        c.ma();
+        d.ma();
+        e.ma();
+
+        try {
+            final int iterations = 10;
+            // Test: calls b.c() in the last iteration.
+            for (int i = 0; i < iterations; i++) {
+                AME6_A a = b;
+                if (i % 3 == 0 && i < iterations - 1) {
+                    a = c;
+                }
+                if (i % 3 == 1 && i < iterations - 1) {
+                    a = d;
+                }
+                if (i % 3 == 2 && i < iterations - 1) {
+                    a = e;
+                }
+                a.mc();
+            }
+            System.out.println();
+        } catch (AbstractMethodError exc) {
+            caught_ame = true;
+            System.out.println();
+            String errorMsg = exc.getMessage();
+            if (enableChecks && errorMsg == null) {
+                System.out.println(exc);
+                throw new RuntimeException("Empty error message of AbstractMethodError.");
+            }
+            if (enableChecks &&
+                !errorMsg.equals(expectedErrorMessageAME6_ItableStub)) {
+                // Thrown via LinkResolver::runtime_resolve_interface_method().
+                System.out.println("Expected: " + expectedErrorMessageAME6_ItableStub + "\n" +
+                                   "but got:  " + errorMsg);
+                System.out.println(exc);
+                throw new RuntimeException("Wrong error message of AbstractMethodError.");
+            }
+            if (enableChecks) {
+                System.out.println("Passed with message: " + errorMsg);
+            }
+        } catch (Throwable exc) {
+            throw exc;
+        }
+
+        // Check that we got the exception at some point.
+        if (enableChecks && !caught_ame) {
+            throw new RuntimeException("Expected AbstractMethodError was not thrown.");
+        }
+    }
+
+
+    public static void main(String[] args) throws Exception {
+        setup_test();
+        test_ame1();
+        test_ame2();
+        test_ame3_1();
+        test_ame3_2();
+        test_ame4();
+        test_ame5_compiled_vtable_stub();
+        test_ame6_compiled_itable_stub();
+    }
+}
+
+// Helper classes to test abstract method error.
+//
+// Errorneous versions of these classes are implemented in java
+// assembler.
+
+
+// -------------------------------------------------------------------------
+// This error should be detected interpreted.
+//
+// Class hierachy:
+//
+//            C     // interface, defines aFunctionOfMyInterface()
+//            |
+//      A     |     // interface
+//      |     |
+//      B     |     // abstract class, defines anAbstractMethod()
+//       \   /
+//         E        // errorneous class implementation lacks methods C::aFunctionOfMyInterface()
+//                                                                   B::anAbstractMethod()
+interface AME1_A {
+
+    public String firstFunctionOfMyInterface0();
+
+    public String secondFunctionOfMyInterface0();
+}
+
+abstract class AME1_B implements AME1_A {
+
+    abstract public String firstAbstractMethod();
+
+    abstract public String secondAbstractMethod();
+
+    abstract public String anAbstractMethod();
+}
+
+interface AME1_C {
+
+    public String firstFunctionOfMyInterface();
+
+    public String secondFunctionOfMyInterface();
+
+    public String aFunctionOfMyInterface();
+}
+
+class AME1_D extends AME1_B implements AME1_C {
+
+    public AME1_D() {
+    }
+
+    public String firstAbstractMethod() {
+        return this.getClass().getName();
+    }
+
+    public String secondAbstractMethod() {
+        return this.getClass().getName();
+    }
+
+    public String anAbstractMethod() {
+        return this.getClass().getName();
+    }
+
+    public String firstFunctionOfMyInterface0() {
+        return this.getClass().getName();
+    }
+
+    public String secondFunctionOfMyInterface0() {
+        return this.getClass().getName();
+    }
+
+    public String firstFunctionOfMyInterface() {
+        return this.getClass().getName();
+    }
+
+    public String secondFunctionOfMyInterface() {
+        return this.getClass().getName();
+    }
+
+    public String aFunctionOfMyInterface() {
+        return this.getClass().getName();
+    }
+}
+
+class AME1_E extends AME1_B implements AME1_C {
+
+    public AME1_E() {
+    }
+
+    public String firstAbstractMethod() {
+        return this.getClass().getName();
+    }
+
+    public String secondAbstractMethod() {
+        return this.getClass().getName();
+    }
+
+    // This method is missing in the .jasm implementation.
+    public String anAbstractMethod() {
+        return this.getClass().getName();
+    }
+
+    public String firstFunctionOfMyInterface0() {
+        return this.getClass().getName();
+    }
+
+    public String secondFunctionOfMyInterface0() {
+        return this.getClass().getName();
+    }
+
+    public String firstFunctionOfMyInterface() {
+        return this.getClass().getName();
+    }
+
+    public String secondFunctionOfMyInterface() {
+        return this.getClass().getName();
+    }
+
+    // This method is missing in the .jasm implementation.
+    public String aFunctionOfMyInterface() {
+        return this.getClass().getName();
+    }
+}
+
+// -------------------------------------------------------------------------
+// This error should be detected interpreted.
+//
+// Class hierachy:
+//
+//      A   // an interface declaring aFunctionOfMyInterface()
+//      |
+//      B   // an abstract class
+//      |
+//      C   // errorneous implementation lacks method A::aFunctionOfMyInterface()
+//
+interface AME2_A {
+    public void aFunctionOfMyInterface();
+}
+
+abstract class AME2_B implements AME2_A {
+    abstract public void fun2();
+}
+
+class ImplementsAllFunctions extends AME2_B {
+
+    public ImplementsAllFunctions() {}
+
+    public void fun2() {
+        //System.out.print("You called public void ImplementsAllFunctions::fun2().\n");
+    }
+
+    public void aFunctionOfMyInterface() {
+        //System.out.print("You called public void ImplementsAllFunctions::aFunctionOfMyInterface()\n");
+    }
+}
+
+class AME2_C extends AME2_B {
+
+    public AME2_C() {}
+
+    public void fun2() {
+        //System.out.print("You called public void AME2_C::fun2().\n");
+    }
+
+    // This method is missing in the .jasm implementation.
+    public void aFunctionOfMyInterface() {
+        //System.out.print("You called public void AME2_C::aFunctionOfMyInterface()\n");
+    }
+}
+
+// -----------------------------------------------------------------------
+// Test AbstractMethod error shadowing existing implementation.
+//
+// Class hierachy:
+//
+//           A           // a class implementing m()
+//           |
+//           B           // an abstract class defining m() abstract
+//           |
+//           C           // an errorneous class lacking an implementation of m()
+//
+class AME3_A {
+    public void ma() {
+        System.out.print("A.ma() ");
+    }
+}
+
+abstract class AME3_B extends AME3_A {
+    public abstract void ma();
+}
+
+class AME3_C extends AME3_B {
+    // This method is missing in the .jasm implementation.
+    public void ma() {
+        System.out.print("C.ma() ");
+    }
+}
+
+// -----------------------------------------------------------------------
+// Test AbstractMethod error shadowing existing implementation. In
+// this test there are several subclasses of the abstract class.
+//
+// Class hierachy:
+//
+//           A           // A: a class implementing ma()
+//           |
+//           B           // B: an abstract class defining ma() abstract
+//        /  | \
+//       C   D  E        // E: an errorneous class lacking an implementation of ma()
+//
+class AME4_A {
+    public void ma() {
+        System.out.print("A.ma() ");
+    }
+}
+
+abstract class AME4_B extends AME4_A {
+    public abstract void ma();
+}
+
+class AME4_C extends AME4_B {
+    public void ma() {
+        System.out.print("C.ma() ");
+    }
+}
+
+class AME4_D extends AME4_B {
+    public void ma() {
+        System.out.print("D.ma() ");
+    }
+}
+
+class AME4_E extends AME4_B {
+    // This method is missing in the .jasm implementation.
+    public void ma() {
+        System.out.print("E.ma() ");
+    }
+}
+
+// -------------------------------------------------------------------------
+// This error should be detected while processing the vtable stub.
+//
+// Class hierachy:
+//
+//              A__     // abstract
+//             /|\ \
+//            C D E \
+//                   B  // Bad class, missing method implementation.
+//
+// Test:
+// - Call D.mc() / E.mc() / F.mc() several times to force real vtable call constrution
+// - Call errorneous B.mc() in the end to raise the AbstraceMethodError
+
+abstract class AME5_A {
+    abstract void ma();
+    abstract void mb();
+    abstract void mc();
+}
+
+class AME5_B extends AME5_A {
+    void ma() {
+        System.out.print("B.ma() ");
+    }
+
+    void mb() {
+        System.out.print("B.mb() ");
+    }
+
+    // This method is missing in the .jasm implementation.
+    void mc() {
+        System.out.print("B.mc() ");
+    }
+}
+
+class AME5_C extends AME5_A {
+    void ma() {
+        System.out.print("C.ma() ");
+    }
+
+    void mb() {
+        System.out.print("C.mb() ");
+    }
+
+    void mc() {
+        System.out.print("C.mc() ");
+    }
+}
+
+class AME5_D extends AME5_A {
+    void ma() {
+        System.out.print("D.ma() ");
+    }
+
+    void mb() {
+        System.out.print("D.mb() ");
+    }
+
+    void mc() {
+        System.out.print("D.mc() ");
+    }
+}
+
+class AME5_E extends AME5_A {
+    void ma() {
+       System.out.print("E.ma() ");
+   }
+
+   void mb() {
+       System.out.print("E.mb() ");
+   }
+
+   void mc() {
+       System.out.print("E.mc() ");
+   }
+}
+
+//-------------------------------------------------------------------------
+// Test AbstractMethod error detected while processing
+// the itable stub.
+//
+// Class hierachy:
+//
+//           A__   (interface)
+//          /|\ \
+//         C D E \
+//                B (bad class, missing method)
+//
+// Test:
+// - Call D.mc() / E.mc() / F.mc() several times to force real itable call constrution
+// - Call errorneous B.mc() in the end to raise the AbstraceMethodError
+
+interface AME6_A {
+    abstract void ma();
+    abstract void mb();
+    abstract void mc();
+}
+
+class AME6_B implements AME6_A {
+    public void ma() {
+        System.out.print("B.ma() ");
+    }
+
+    public void mb() {
+        System.out.print("B.mb() ");
+    }
+
+    // This method is missing in the .jasm implementation.
+    public void mc() {
+        System.out.print("B.mc() ");
+    }
+}
+
+class AME6_C implements AME6_A {
+    public void ma() {
+        System.out.print("C.ma() ");
+    }
+
+    public void mb() {
+        System.out.print("C.mb() ");
+    }
+
+    public void mc() {
+        System.out.print("C.mc() ");
+    }
+}
+
+class AME6_D implements AME6_A {
+    public void ma() {
+        System.out.print("D.ma() ");
+    }
+
+    public void mb() {
+        System.out.print("D.mb() ");
+    }
+
+    public void mc() {
+        System.out.print("D.mc() ");
+    }
+}
+
+class AME6_E implements AME6_A {
+    public void ma() {
+        System.out.print("E.ma() ");
+    }
+
+    public void mb() {
+        System.out.print("E.mb() ");
+    }
+
+    public void mc() {
+        System.out.print("E.mc() ");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/ICC_B.jasm	Thu Feb 08 09:23:49 2018 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 SAP SE. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+class ICC_B implements ICC_iA {
+
+    public Method "<init>":"()V"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokespecial Method java/lang/Object."<init>":"()V";
+        return;
+    }
+
+  public Method a:"()V"
+        stack 2 locals 1
+    {
+        getstatic     Field java/lang/System.out:"Ljava/io/PrintStream;";
+        ldc           String "B.a()";
+        invokevirtual Method java/io/PrintStream.print:"(Ljava/lang/String;)V";
+        return;
+    }
+
+  public Method b:"()V"
+        stack 2 locals 1
+    {
+        getstatic     Field java/lang/System.out:"Ljava/io/PrintStream;";
+        ldc           String "B.b()";
+        invokevirtual Method java/io/PrintStream.print:"(Ljava/lang/String;)V";
+        return;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/ImplementsSomeInterfaces.jasm	Thu Feb 08 09:23:49 2018 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 SAP SE. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+
+
+
+class ImplementsSomeInterfaces extends AbstractICCE0 {
+
+    public Method "<init>":"()V"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokespecial Method AbstractICCE0."<init>":"()V";
+        return;
+    }
+
+  public Method firstAbstractMethod:"()Ljava/lang/String;"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokevirtual Method java/lang/Object.getClass:"()Ljava/lang/Class;";
+        invokevirtual Method java/lang/Class.getName:"()Ljava/lang/String;";
+        areturn;
+    }
+
+  public Method secondAbstractMethod:"()Ljava/lang/String;"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokevirtual Method java/lang/Object.getClass:"()Ljava/lang/Class;";
+        invokevirtual Method java/lang/Class.getName:"()Ljava/lang/String;";
+        areturn;
+    }
+
+  public Method firstFunctionOfMyInterface0:"()Ljava/lang/String;"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokevirtual Method java/lang/Object.getClass:"()Ljava/lang/Class;";
+        invokevirtual Method java/lang/Class.getName:"()Ljava/lang/String;";
+        areturn;
+    }
+
+  public Method secondFunctionOfMyInterface0:"()Ljava/lang/String;"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokevirtual Method java/lang/Object.getClass:"()Ljava/lang/Class;";
+        invokevirtual Method java/lang/Class.getName:"()Ljava/lang/String;";
+        areturn;
+    }
+
+  public Method firstFunctionOfMyInterface:"()Ljava/lang/String;"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokevirtual Method java/lang/Object.getClass:"()Ljava/lang/Class;";
+        invokevirtual Method java/lang/Class.getName:"()Ljava/lang/String;";
+        areturn;
+    }
+
+  public Method secondFunctionOfMyInterface:"()Ljava/lang/String;"
+        stack 1 locals 1
+    {
+        aload_0;
+        invokevirtual Method java/lang/Object.getClass:"()Ljava/lang/Class;";
+        invokevirtual Method java/lang/Class.getName:"()Ljava/lang/String;";
+        areturn;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/IncompatibleClassChangeErrorTest.java	Thu Feb 08 09:23:49 2018 +0100
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 SAP SE. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Check that the verbose message of ICCE is printed correctly.
+ *          The test forces errors in vtable stubs and interpreter.
+ * @requires !(os.arch=="arm")
+ * @library /test/lib /
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @compile IncompatibleClassChangeErrorTest.java
+ * @compile ImplementsSomeInterfaces.jasm ICC_B.jasm
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ *                   -XX:-BackgroundCompilation -XX:-Inline
+ *                   -XX:CompileCommand=exclude,IncompatibleClassChangeErrorTest::test_iccInt
+ *                   IncompatibleClassChangeErrorTest
+ */
+
+import sun.hotspot.WhiteBox;
+import compiler.whitebox.CompilerWhiteBoxTest;
+import java.lang.reflect.Method;
+
+// This test assembles an errorneous installation of classes.
+// First, compile the test by @compile. This results in a legal set
+// of classes.
+// Then, with jasm, generate incompatible classes that overwrite
+// the class files in the build directory.
+// Last, call the real tests throwing IncompatibleClassChangeErrors
+// and check the messages generated.
+public class IncompatibleClassChangeErrorTest {
+
+    private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+
+    private static boolean enableChecks = true;
+
+    private static String expectedErrorMessageInterpreted =
+        "Class ImplementsSomeInterfaces " +
+        "does not implement the requested interface InterfaceICCE1";
+    private static String expectedErrorMessageCompiled =
+        "Class ICC_B does not implement the requested interface ICC_iB";
+        // old message: "vtable stub"
+
+    public static void setup_test() {
+        // Assure all exceptions are loaded.
+        new AbstractMethodError();
+        new IncompatibleClassChangeError();
+
+        enableChecks = false;
+        // Warmup
+        System.out.println("warmup:");
+        test_iccInt();
+        test_icc_compiled_itable_stub();
+        enableChecks = true;
+
+        // Compile
+        try {
+            Method method = IncompatibleClassChangeErrorTest.class.getMethod("test_icc_compiled_itable_stub");
+            WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
+            if (!WHITE_BOX.isMethodCompiled(method)) {
+                throw new RuntimeException(method.getName() + " is not compiled");
+            }
+            method = ICC_C.class.getMethod("b");
+            WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
+            if (!WHITE_BOX.isMethodCompiled(method)) {
+                throw new RuntimeException("ICC_C." + method.getName() + " is not compiled");
+            }
+            method = ICC_D.class.getMethod("b");
+            WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
+            if (!WHITE_BOX.isMethodCompiled(method)) {
+                throw new RuntimeException("ICC_D." + method.getName() + " is not compiled");
+            }
+            method = ICC_E.class.getMethod("b");
+            WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
+            if (!WHITE_BOX.isMethodCompiled(method)) {
+                throw new RuntimeException("ICC_E." + method.getName() + " is not compiled");
+            }
+        } catch (NoSuchMethodException e) { }
+        System.out.println("warmup done.");
+    }
+
+    // Should never be compiled.
+    public static void test_iccInt() {
+        boolean caught_icc = false;
+        try {
+            InterfaceICCE1 objectInterface = new ImplementsSomeInterfaces();
+            // IncompatibleClassChangeError gets thrown in
+            // - TemplateTable::invokeinterface()
+            // - LinkResolver::runtime_resolve_interface_method()
+            objectInterface.aFunctionOfMyInterface();
+        } catch (IncompatibleClassChangeError e) {
+            String errorMsg = e.getMessage();
+            if (enableChecks && !errorMsg.equals(expectedErrorMessageInterpreted)) {
+                System.out.println("Expected: " + expectedErrorMessageInterpreted + "\n" +
+                                   "but got:  " + errorMsg);
+                throw new RuntimeException("Wrong error message of IncompatibleClassChangeError.");
+            }
+            caught_icc = true;
+        } catch (Throwable e) {
+            throw new RuntimeException("Caught unexpected exception: " + e);
+        }
+
+        // Check we got the exception.
+        if (!caught_icc) {
+            throw new RuntimeException("Expected IncompatibleClassChangeError was not thrown.");
+        }
+    }
+
+    // -------------------------------------------------------------------------
+    // Test AbstractMethodErrors detected in itable stubs.
+    // Note: How can we verify that we really stepped through the vtable stub?
+    // - Bimorphic inlining should not happen since we have no profiling data when
+    //   we compile the method
+    // - As a result, an inline cache call should be generated
+    // - This inline cache call is patched into a real vtable call at the first
+    //   re-resolve, which happens constantly during the first 10 iterations of the loop.
+    // => we should be fine! :-)
+    public static void test_icc_compiled_itable_stub() {
+        // Allocated the objects we need and call a valid method.
+        boolean caught_icc = false;
+        ICC_B b = new ICC_B();
+        ICC_C c = new ICC_C();
+        ICC_D d = new ICC_D();
+        ICC_E e = new ICC_E();
+        b.a();
+        c.a();
+        d.a();
+        e.a();
+
+        try {
+            final int iterations = 10;
+            // Test: calls b.b() in the last iteration.
+            for (int i = 0; i < iterations; i++) {
+                ICC_iB a = b;
+                if (i % 3 == 0 && i < iterations - 1) {
+                    a = c;
+                }
+                if (i % 3 == 1 && i < iterations - 1) {
+                    a = d;
+                }
+                if (i % 3 == 2 && i < iterations - 1) {
+                    a = e;
+                }
+                a.b();
+            }
+        } catch (AbstractMethodError exc) {
+            // It's a subclass of IncompatibleClassChangeError, so we must catch this first.
+            System.out.println();
+            System.out.println(exc);
+            if (enableChecks) {
+                String errorMsg = exc.getMessage();
+                if (errorMsg == null) {
+                    throw new RuntimeException("Caught unexpected AbstractMethodError with empty message.");
+                }
+                throw new RuntimeException("Caught unexpected AbstractMethodError.");
+            }
+        } catch (IncompatibleClassChangeError exc) {
+            caught_icc = true;
+            System.out.println();
+            String errorMsg = exc.getMessage();
+            if (enableChecks && errorMsg == null) {
+                System.out.println(exc);
+                throw new RuntimeException("Empty error message of IncompatibleClassChangeError.");
+            }
+            if (enableChecks &&
+                !errorMsg.equals(expectedErrorMessageCompiled)) {
+                System.out.println("Expected: " + expectedErrorMessageCompiled + "\n" +
+                                   "but got:  " + errorMsg);
+                System.out.println(exc);
+                throw new RuntimeException("Wrong error message of IncompatibleClassChangeError.");
+            }
+            if (enableChecks) {
+                System.out.println("Passed with message: " + errorMsg);
+            }
+        } catch (Throwable exc) {
+            throw exc; // new RuntimeException("Caught unexpected exception: " + exc);
+        }
+
+        // Check we got the exception at some point.
+        if (enableChecks && !caught_icc) {
+            throw new RuntimeException("Expected IncompatibleClassChangeError was not thrown.");
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        setup_test();
+        test_iccInt();
+        test_icc_compiled_itable_stub();
+    }
+}
+
+
+// Helper classes to test incompatible class change in interpreter.
+//
+// The test also contains .jasm files with implementations
+// of the classes that shall generate the errors.
+
+
+//   I0         // interface defining aFunctionOfMyInterface()
+//   |
+//   |    I1    // interface
+//   |     |
+//   A0    |    // abstract class
+//    \   /
+//      C       // class not implementing I1 and
+//                       not implementing I0::aFunctionOfMyInterface()
+//
+// Test is expected to throw error because of missing interface and not
+// because of missing method.
+
+interface InterfaceICCE0 {
+    public String firstFunctionOfMyInterface0();
+    public String secondFunctionOfMyInterface0();
+}
+
+interface InterfaceICCE1 {
+
+    public String firstFunctionOfMyInterface();
+
+    public String secondFunctionOfMyInterface();
+
+    public String aFunctionOfMyInterface();
+}
+
+abstract class AbstractICCE0 implements InterfaceICCE0 {
+    abstract public String firstAbstractMethod();
+    abstract public String secondAbstractMethod();
+
+    abstract public String anAbstractMethod();
+}
+
+class ImplementsSomeInterfaces extends
+        AbstractICCE0
+    // This interface is missing in the .jasm implementation.
+    implements InterfaceICCE1
+{
+
+    public String firstAbstractMethod() {
+        return this.getClass().getName();
+    }
+
+    public String secondAbstractMethod() {
+        return this.getClass().getName();
+    }
+
+    // This method is missing in the .jasm implementation.
+    public String anAbstractMethod() {
+        return this.getClass().getName();
+    }
+
+    public String firstFunctionOfMyInterface0() {
+        return this.getClass().getName();
+    }
+
+    public String secondFunctionOfMyInterface0() {
+        return this.getClass().getName();
+    }
+
+    public String firstFunctionOfMyInterface() {
+        return this.getClass().getName();
+    }
+
+    public String secondFunctionOfMyInterface() {
+        return this.getClass().getName();
+    }
+
+    // This method is missing in the .jasm implementation.
+    public String aFunctionOfMyInterface() {
+        return this.getClass().getName();
+    }
+}
+
+// Helper classes to test incompatible class change in itable stub.
+//
+// Class hierachy:
+//
+//          iA,iB   (interfaces)
+//          /|\ \
+//         C D E \
+//                B (bad class, missing interface implementation)
+
+interface ICC_iA {
+    public void a();
+}
+
+interface ICC_iB {
+    public void b();
+}
+
+// This is the errorneous class. A variant of it not
+// implementing ICC_iB is copied into the test before
+// it is run.
+class ICC_B implements ICC_iA,
+                       // This interface is missing in the .jasm implementation.
+                       ICC_iB {
+    public void a() {
+        System.out.print("B.a() ");
+    }
+
+    public void b() {
+        System.out.print("B.b() ");
+    }
+}
+
+class ICC_C implements ICC_iA, ICC_iB {
+    public void a() {
+        System.out.print("C.a() ");
+    }
+
+    public void b() {
+        System.out.print("C.b() ");
+    }
+}
+
+class ICC_D implements ICC_iA, ICC_iB {
+    public void a() {
+        System.out.print("D.a() ");
+    }
+
+    public void b() {
+        System.out.print("D.b() ");
+    }
+}
+
+class ICC_E implements ICC_iA, ICC_iB {
+    public void a() {
+        System.out.print("E.a() ");
+    }
+
+    public void b() {
+        System.out.print("E.b() ");
+    }
+}