8020489: VM crash when non-existent interface called by invokespecial
Reviewed-by: kamg, coleenp
This commit is contained in:
parent
fefcbb92f2
commit
c0f4055c78
@ -870,7 +870,6 @@ class ErasedShadowChecker : public ShadowChecker {
|
|||||||
: ShadowChecker(thread, name, holder, target) {}
|
: ShadowChecker(thread, name, holder, target) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Find the unique qualified candidate from the perspective of the super_class
|
// Find the unique qualified candidate from the perspective of the super_class
|
||||||
// which is the resolved_klass, which must be an immediate superinterface
|
// which is the resolved_klass, which must be an immediate superinterface
|
||||||
// of klass
|
// of klass
|
||||||
@ -884,43 +883,48 @@ Method* find_erased_super_default(InstanceKlass* current_class, InstanceKlass* s
|
|||||||
|
|
||||||
if (family != NULL) {
|
if (family != NULL) {
|
||||||
family->determine_target(current_class, CHECK_NULL); // get target from current_class
|
family->determine_target(current_class, CHECK_NULL); // get target from current_class
|
||||||
}
|
|
||||||
|
|
||||||
if (family->has_target()) {
|
if (family->has_target()) {
|
||||||
Method* target = family->get_selected_target();
|
Method* target = family->get_selected_target();
|
||||||
InstanceKlass* holder = InstanceKlass::cast(target->method_holder());
|
InstanceKlass* holder = InstanceKlass::cast(target->method_holder());
|
||||||
|
|
||||||
// Verify that the identified method is valid from the context of
|
// Verify that the identified method is valid from the context of
|
||||||
// the current class, which is the caller class for invokespecial
|
// the current class, which is the caller class for invokespecial
|
||||||
// link resolution, i.e. ensure there it is not shadowed.
|
// link resolution, i.e. ensure there it is not shadowed.
|
||||||
// You can use invokespecial to disambiguate interface methods, but
|
// You can use invokespecial to disambiguate interface methods, but
|
||||||
// you can not use it to skip over an interface method that would shadow it.
|
// you can not use it to skip over an interface method that would shadow it.
|
||||||
ErasedShadowChecker checker(THREAD, target->name(), holder, super_class);
|
ErasedShadowChecker checker(THREAD, target->name(), holder, super_class);
|
||||||
checker.run(current_class);
|
checker.run(current_class);
|
||||||
|
|
||||||
if (checker.found_shadow()) {
|
if (checker.found_shadow()) {
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if (TraceDefaultMethods) {
|
if (TraceDefaultMethods) {
|
||||||
tty->print_cr(" Only candidate found was shadowed.");
|
tty->print_cr(" Only candidate found was shadowed.");
|
||||||
}
|
}
|
||||||
#endif // ndef PRODUCT
|
#endif // ndef PRODUCT
|
||||||
THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(),
|
THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(),
|
||||||
"Accessible default method not found", NULL);
|
"Accessible default method not found", NULL);
|
||||||
|
} else {
|
||||||
|
#ifndef PRODUCT
|
||||||
|
if (TraceDefaultMethods) {
|
||||||
|
family->print_sig_on(tty, target->signature(), 1);
|
||||||
|
}
|
||||||
|
#endif // ndef PRODUCT
|
||||||
|
return target;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
#ifndef PRODUCT
|
assert(family->throws_exception(), "must have target or throw");
|
||||||
if (TraceDefaultMethods) {
|
THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(),
|
||||||
family->print_sig_on(tty, target->signature(), 1);
|
family->get_exception_message()->as_C_string(), NULL);
|
||||||
}
|
}
|
||||||
#endif // ndef PRODUCT
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
assert(family->throws_exception(), "must have target or throw");
|
// no method found
|
||||||
THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(),
|
ResourceMark rm(THREAD);
|
||||||
family->get_exception_message()->as_C_string(), NULL);
|
THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(),
|
||||||
|
Method::name_and_sig_as_C_string(current_class,
|
||||||
|
method_name, sig), NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is called during linktime when we find an invokespecial call that
|
// This is called during linktime when we find an invokespecial call that
|
||||||
// refers to a direct superinterface. It indicates that we should find the
|
// refers to a direct superinterface. It indicates that we should find the
|
||||||
// default method in the hierarchy of that superinterface, and if that method
|
// default method in the hierarchy of that superinterface, and if that method
|
||||||
|
Loading…
x
Reference in New Issue
Block a user