--- 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());
+}