--- old/src/hotspot/cpu/zero/methodHandles_zero.cpp 2018-06-05 11:36:48.931860133 +0200 +++ new/src/hotspot/cpu/zero/methodHandles_zero.cpp 2018-06-05 11:36:48.645860789 +0200 @@ -26,6 +26,7 @@ #include "precompiled.hpp" #include "interpreter/cppInterpreterGenerator.hpp" #include "interpreter/interpreter.hpp" +#include "interpreter/interpreterRuntime.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" #include "oops/method.inline.hpp" @@ -65,6 +66,37 @@ } +void MethodHandles::throw_AME(Klass* rcvr, Method* interface_method, TRAPS) { + + JavaThread *thread = (JavaThread *) THREAD; + // Set up the frame anchor if it isn't already + bool has_last_Java_frame = thread->has_last_Java_frame(); + if (!has_last_Java_frame) { + intptr_t *sp = thread->zero_stack()->sp(); + ZeroFrame *frame = thread->top_zero_frame(); + while (frame) { + if (frame->is_interpreter_frame()) { + interpreterState istate = + frame->as_interpreter_frame()->interpreter_state(); + if (istate->self_link() == istate) + break; + } + + sp = ((intptr_t *) frame) + 1; + frame = frame->next(); + } + + assert(frame != NULL, "must be"); + thread->set_last_Java_frame(frame, sp); + } + InterpreterRuntime::throw_AbstractMethodErrorVerbose(thread, rcvr, interface_method); + // Reset the frame anchor if necessary + if (!has_last_Java_frame) { + thread->reset_last_Java_frame(); + } + +} + int MethodHandles::method_handle_entry_invokeBasic(Method* method, intptr_t UNUSED, TRAPS) { JavaThread *thread = (JavaThread *) THREAD; @@ -124,8 +156,15 @@ itableMethodEntry* im = ki->first_method_entry(recv->klass()); Method* vmtarget = im[vmindex].method(); - - invoke_target(vmtarget, THREAD); + // Check that the vmtarget entry is non-null. A null entry means + // that the method no longer exists (got deleted) or is private. + // Private class methods can never be an implementation of an + // interface method. In those cases, throw AME. + if (vmtarget != NULL) { + invoke_target(vmtarget, THREAD); + } else { + throw_AME(recv->klass(), target, THREAD); + } return 0; }