src/hotspot/share/runtime/sharedRuntime.cpp
changeset 49368 2ed1c37df3a5
parent 49359 59f6547e151f
child 49400 d2dd7e7d2044
--- 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