8031059: invokestatic: ICCE trying to invoke static method when it clashes with an abstract method inherited from an interface

Do not create AME overpass if there is a matching static method

Reviewed-by: lfoltan, coleenp, kamg
This commit is contained in:
Harold Seigel 2014-01-14 16:27:35 -05:00
parent e5a5aefdfb
commit 44a8bf65f3

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -390,6 +390,20 @@ class MethodFamily : public ResourceObj {
Symbol* get_exception_message() { return _exception_message; }
Symbol* get_exception_name() { return _exception_name; }
// Return true if the specified klass has a static method that matches
// the name and signature of the target method.
bool has_matching_static(InstanceKlass* root) {
if (_members.length() > 0) {
Pair<Method*,QualifiedState> entry = _members.at(0);
Method* impl = root->find_method(entry.first->name(),
entry.first->signature());
if ((impl != NULL) && impl->is_static()) {
return true;
}
}
return false;
}
// Either sets the target or the exception error message
void determine_target(InstanceKlass* root, TRAPS) {
if (has_target() || throws_exception()) {
@ -416,19 +430,26 @@ class MethodFamily : public ResourceObj {
}
if (num_defaults == 0) {
if (qualified_methods.length() == 0) {
_exception_message = generate_no_defaults_message(CHECK);
} else {
assert(root != NULL, "Null root class");
_exception_message = generate_method_message(root->name(), qualified_methods.at(0), CHECK);
// If the root klass has a static method with matching name and signature
// then do not generate an overpass method because it will hide the
// static method during resolution.
if (!has_matching_static(root)) {
if (qualified_methods.length() == 0) {
_exception_message = generate_no_defaults_message(CHECK);
} else {
assert(root != NULL, "Null root class");
_exception_message = generate_method_message(root->name(), qualified_methods.at(0), CHECK);
}
_exception_name = vmSymbols::java_lang_AbstractMethodError();
}
_exception_name = vmSymbols::java_lang_AbstractMethodError();
// If only one qualified method is default, select that
} else if (num_defaults == 1) {
_selected_target = qualified_methods.at(default_index);
} else if (num_defaults > 1) {
_exception_message = generate_conflicts_message(&qualified_methods,CHECK);
_exception_name = vmSymbols::java_lang_IncompatibleClassChangeError();
} else if (num_defaults > 1 && !has_matching_static(root)) {
_exception_message = generate_conflicts_message(&qualified_methods,CHECK);
_exception_name = vmSymbols::java_lang_IncompatibleClassChangeError();
if (TraceDefaultMethods) {
_exception_message->print_value_on(tty);
tty->print_cr("");