< prev index next >
src/hotspot/share/interpreter/linkResolver.cpp
Print this page
rev 49103 : 8197405: Improve messages of AbstractMethodErrors and IncompatibleClassChangeErrors.
Reviewed-by: coleenp, dholmes, mdoerr, njian
@@ -1341,22 +1341,21 @@
// a missing receiver might result in a bogus lookup.
assert(resolved_method->method_holder()->is_linked(), "must be linked");
// 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));
} else {
// at this point we are sure that resolved_method is virtual and not
// a default or miranda method; therefore, it must have a valid vtable index.
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.
if (vtable_index == Method::nonvirtual_vtable_index) {
assert(resolved_method->can_be_statically_bound(), "cannot override this method");
@@ -1366,24 +1365,17 @@
}
}
// 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)) {
trace_method_resolution("invokevirtual selected method: receiver-class:",
recv_klass, resolved_klass, selected_method,
@@ -1435,57 +1427,50 @@
}
// 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);
}
}
methodHandle LinkResolver::linktime_resolve_interface_method_or_null(
@@ -1771,5 +1756,40 @@
THREAD);
Exceptions::wrap_dynamic_exception(CHECK);
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());
+}
< prev index next >