8031059: invokestatic: ICCE trying to invoke static method when it clashes with an abstract method inherited from an interface
Summary: Do not create AME overpass if there is a matching static method
Reviewed-by: lfoltan, coleenp, kamg
--- a/hotspot/src/share/vm/classfile/defaultMethods.cpp Tue Jan 14 13:51:47 2014 -0500
+++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp Tue Jan 14 16:27:35 2014 -0500
@@ -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 @@
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 @@
}
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("");