mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-12 06:29:37 +00:00
8356942: invokeinterface Throws AbstractMethodError Instead of IncompatibleClassChangeError
Reviewed-by: coleenp, iklam
This commit is contained in:
parent
5cf672e778
commit
f36147b326
@ -1180,38 +1180,42 @@ void klassItable::check_constraints(GrowableArray<Method*>* supers, TRAPS) {
|
||||
Method* interface_method = supers->at(i); // method overridden
|
||||
|
||||
if (target != nullptr && interface_method != nullptr) {
|
||||
InstanceKlass* method_holder = target->method_holder();
|
||||
InstanceKlass* interf = interface_method->method_holder();
|
||||
HandleMark hm(THREAD);
|
||||
Handle method_holder_loader(THREAD, method_holder->class_loader());
|
||||
Handle interface_loader(THREAD, interf->class_loader());
|
||||
// Do not check loader constraints for overpass methods because overpass
|
||||
// methods are created by the jvm to throw exceptions.
|
||||
if (!target->is_overpass()) {
|
||||
InstanceKlass* method_holder = target->method_holder();
|
||||
InstanceKlass* interf = interface_method->method_holder();
|
||||
HandleMark hm(THREAD);
|
||||
Handle method_holder_loader(THREAD, method_holder->class_loader());
|
||||
Handle interface_loader(THREAD, interf->class_loader());
|
||||
|
||||
if (method_holder_loader() != interface_loader()) {
|
||||
ResourceMark rm(THREAD);
|
||||
Symbol* failed_type_symbol =
|
||||
SystemDictionary::check_signature_loaders(target->signature(),
|
||||
_klass,
|
||||
method_holder_loader,
|
||||
interface_loader,
|
||||
true);
|
||||
if (failed_type_symbol != nullptr) {
|
||||
stringStream ss;
|
||||
ss.print("loader constraint violation in interface itable"
|
||||
" initialization for class %s: when selecting method '",
|
||||
_klass->external_name());
|
||||
interface_method->print_external_name(&ss),
|
||||
ss.print("' the class loader %s for super interface %s, and the class"
|
||||
" loader %s of the selected method's %s, %s have"
|
||||
" different Class objects for the type %s used in the signature (%s; %s)",
|
||||
interf->class_loader_data()->loader_name_and_id(),
|
||||
interf->external_name(),
|
||||
method_holder->class_loader_data()->loader_name_and_id(),
|
||||
method_holder->external_kind(),
|
||||
method_holder->external_name(),
|
||||
failed_type_symbol->as_klass_external_name(),
|
||||
interf->class_in_module_of_loader(false, true),
|
||||
method_holder->class_in_module_of_loader(false, true));
|
||||
THROW_MSG(vmSymbols::java_lang_LinkageError(), ss.as_string());
|
||||
if (method_holder_loader() != interface_loader()) {
|
||||
ResourceMark rm(THREAD);
|
||||
Symbol* failed_type_symbol =
|
||||
SystemDictionary::check_signature_loaders(target->signature(),
|
||||
_klass,
|
||||
method_holder_loader,
|
||||
interface_loader,
|
||||
true);
|
||||
if (failed_type_symbol != nullptr) {
|
||||
stringStream ss;
|
||||
ss.print("loader constraint violation in interface itable"
|
||||
" initialization for class %s: when selecting method '",
|
||||
_klass->external_name());
|
||||
interface_method->print_external_name(&ss),
|
||||
ss.print("' the class loader %s for super interface %s, and the class"
|
||||
" loader %s of the selected method's %s, %s have"
|
||||
" different Class objects for the type %s used in the signature (%s; %s)",
|
||||
interf->class_loader_data()->loader_name_and_id(),
|
||||
interf->external_name(),
|
||||
method_holder->class_loader_data()->loader_name_and_id(),
|
||||
method_holder->external_kind(),
|
||||
method_holder->external_name(),
|
||||
failed_type_symbol->as_klass_external_name(),
|
||||
interf->class_in_module_of_loader(false, true),
|
||||
method_holder->class_in_module_of_loader(false, true));
|
||||
THROW_MSG(vmSymbols::java_lang_LinkageError(), ss.as_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1333,11 +1337,9 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Insta
|
||||
target = LinkResolver::lookup_instance_method_in_klasses(_klass, m->name(), m->signature(),
|
||||
Klass::PrivateLookupMode::skip);
|
||||
}
|
||||
if (target == nullptr || !target->is_public() || target->is_abstract() || target->is_overpass()) {
|
||||
assert(target == nullptr || !target->is_overpass() || target->is_public(),
|
||||
"Non-public overpass method!");
|
||||
if (target == nullptr || !target->is_public() || target->is_abstract()) {
|
||||
// Entry does not resolve. Leave it empty for AbstractMethodError or other error.
|
||||
if (!(target == nullptr) && !target->is_public()) {
|
||||
if (target != nullptr && !target->is_public()) {
|
||||
// Stuff an IllegalAccessError throwing method in there instead.
|
||||
itableOffsetEntry::method_entry(_klass, method_table_offset)[m->itable_index()].
|
||||
initialize(_klass, Universe::throw_illegal_access_error());
|
||||
|
||||
@ -82,6 +82,8 @@ public class ConflictingDefaultsTest extends DefMethTest {
|
||||
* class C implements I, J {}
|
||||
*
|
||||
* TEST: C c = new C(); c.m() ==> ICCE
|
||||
* TEST: I c = new C(); c.m() ==> ICCE
|
||||
* TEST: J c = new C(); c.m() ==> ICCE
|
||||
*/
|
||||
public void testConflict(TestBuilder b) {
|
||||
Interface I = b.intf("I")
|
||||
@ -95,7 +97,13 @@ public class ConflictingDefaultsTest extends DefMethTest {
|
||||
ConcreteClass C = b.clazz("C").implement(I,J).build();
|
||||
|
||||
b.test().callSite(C, C, "m","()I")
|
||||
.throws_(IncompatibleClassChangeError.class)
|
||||
.throwsExact(IncompatibleClassChangeError.class)
|
||||
.done()
|
||||
.test().callSite(I, C, "m","()I")
|
||||
.throwsExact(IncompatibleClassChangeError.class)
|
||||
.done()
|
||||
.test().callSite(J, C, "m","()I")
|
||||
.throwsExact(IncompatibleClassChangeError.class)
|
||||
.done();
|
||||
}
|
||||
|
||||
@ -145,7 +153,7 @@ public class ConflictingDefaultsTest extends DefMethTest {
|
||||
ConcreteClass C = b.clazz("C").implement(J).build();
|
||||
|
||||
b.test().callSite(C, C, "m","()I")
|
||||
.throws_(AbstractMethodError.class)
|
||||
.throwsExact(AbstractMethodError.class)
|
||||
.done();
|
||||
}
|
||||
|
||||
@ -177,16 +185,16 @@ public class ConflictingDefaultsTest extends DefMethTest {
|
||||
.build();
|
||||
|
||||
b.test().callSite(C, C, "m","()I")
|
||||
.throws_(AbstractMethodError.class)
|
||||
.throwsExact(AbstractMethodError.class)
|
||||
.done()
|
||||
.test().callSite(J, C, "m","()I")
|
||||
.throws_(AbstractMethodError.class)
|
||||
.throwsExact(AbstractMethodError.class)
|
||||
.done()
|
||||
.test().callSite(I, C, "m","()I")
|
||||
.throws_(AbstractMethodError.class)
|
||||
.throwsExact(AbstractMethodError.class)
|
||||
.done()
|
||||
.test().callSite(D, D, "m","()I")
|
||||
.throws_(AbstractMethodError.class)
|
||||
.throwsExact(AbstractMethodError.class)
|
||||
.done();
|
||||
}
|
||||
|
||||
@ -218,7 +226,7 @@ public class ConflictingDefaultsTest extends DefMethTest {
|
||||
ConcreteClass C = b.clazz("C").extend(A).implement(K).build();
|
||||
|
||||
b.test().callSite(A, C, "m","()I")
|
||||
.throws_(AbstractMethodError.class)
|
||||
.throwsExact(AbstractMethodError.class)
|
||||
.done();
|
||||
}
|
||||
|
||||
@ -259,13 +267,13 @@ public class ConflictingDefaultsTest extends DefMethTest {
|
||||
ConcreteClass D = b.clazz("D").extend(C).implement(L).build();
|
||||
|
||||
b.test().callSite(I, A, "m","()I")
|
||||
.throws_(IncompatibleClassChangeError.class)
|
||||
.throwsExact(IncompatibleClassChangeError.class)
|
||||
.done()
|
||||
.test().callSite(K, C, "m","()I")
|
||||
.throws_(AbstractMethodError.class)
|
||||
.throwsExact(AbstractMethodError.class)
|
||||
.done()
|
||||
.test().callSite(L, D, "m","()I")
|
||||
.throws_(AbstractMethodError.class)
|
||||
.throwsExact(AbstractMethodError.class)
|
||||
.done();
|
||||
}
|
||||
|
||||
@ -307,10 +315,10 @@ public class ConflictingDefaultsTest extends DefMethTest {
|
||||
.build();
|
||||
|
||||
b.test().callSite(I, A, "m","()I")
|
||||
.throws_(IncompatibleClassChangeError.class)
|
||||
.throwsExact(IncompatibleClassChangeError.class)
|
||||
.done()
|
||||
.test().callSite(L, D, "m","()I")
|
||||
.throws_(AbstractMethodError.class)
|
||||
.throwsExact(AbstractMethodError.class)
|
||||
.done();
|
||||
}
|
||||
|
||||
@ -370,22 +378,22 @@ public class ConflictingDefaultsTest extends DefMethTest {
|
||||
}
|
||||
|
||||
b.test().callSite(A, C, "m", "()I")
|
||||
.throws_(expectedError2)
|
||||
.throwsExact(expectedError2)
|
||||
.done()
|
||||
.test().callSite(C, C, "m", "()I")
|
||||
.throws_(expectedError2)
|
||||
.throwsExact(expectedError2)
|
||||
.done()
|
||||
.test().callSite(J, C, "m", "()I")
|
||||
.throws_(expectedError1)
|
||||
.throwsExact(expectedError1)
|
||||
.done()
|
||||
.test().callSite(I, C, "m", "()I")
|
||||
.throws_(expectedError1)
|
||||
.throwsExact(expectedError1)
|
||||
.done()
|
||||
.test().callSite(C, C, "test_Cmethod_ISMR", "()V")
|
||||
.throws_(expectedError2)
|
||||
.throwsExact(expectedError2)
|
||||
.done()
|
||||
.test().callSite(A, C, "test_Amethod_ISIMR", "()V")
|
||||
.throws_(expectedError2)
|
||||
.throwsExact(expectedError2)
|
||||
.done();
|
||||
}
|
||||
|
||||
@ -486,13 +494,13 @@ public class ConflictingDefaultsTest extends DefMethTest {
|
||||
.test()
|
||||
.callSite(I, C, "m","(I)I")
|
||||
.params(0)
|
||||
.throws_(NoSuchMethodError.class)
|
||||
.throwsExact(NoSuchMethodError.class)
|
||||
.done()
|
||||
|
||||
// J j = new C(); ...
|
||||
.test()
|
||||
.callSite(J, C, "m","()I")
|
||||
.throws_(NoSuchMethodError.class)
|
||||
.throwsExact(NoSuchMethodError.class)
|
||||
.done()
|
||||
.test()
|
||||
.callSite(J, C, "m","(I)I")
|
||||
@ -539,19 +547,19 @@ public class ConflictingDefaultsTest extends DefMethTest {
|
||||
// I i = new C(); ...
|
||||
b.test()
|
||||
.callSite(I, C, "m","()I")
|
||||
.throws_(IncompatibleClassChangeError.class)
|
||||
.throwsExact(IncompatibleClassChangeError.class)
|
||||
.done()
|
||||
|
||||
// J j = new C(); ...
|
||||
.test()
|
||||
.callSite(J, C, "m","()I")
|
||||
.throws_(IncompatibleClassChangeError.class)
|
||||
.throwsExact(IncompatibleClassChangeError.class)
|
||||
.done()
|
||||
|
||||
// C c = new C(); ...
|
||||
.test()
|
||||
.callSite(C, C, "m","()I")
|
||||
.throws_(IncompatibleClassChangeError.class)
|
||||
.throwsExact(IncompatibleClassChangeError.class)
|
||||
.done()
|
||||
.test()
|
||||
.callSite(C, C, "m","(I)I")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user