--- a/hotspot/src/share/vm/classfile/defaultMethods.cpp Fri Nov 08 23:49:20 2013 +0000
+++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp Wed Nov 13 07:31:26 2013 -0800
@@ -171,8 +171,12 @@
}
bool is_cancelled() const { return _cancelled; }
+ // This code used to skip interface classes because their only
+ // superclass was j.l.Object which would be also covered by class
+ // superclass hierarchy walks. Now that the starting point can be
+ // an interface, we must ensure we catch j.l.Object as the super.
static bool has_super(InstanceKlass* cls) {
- return cls->super() != NULL && !cls->is_interface();
+ return cls->super() != NULL;
}
Node* node_at_depth(int i) const {
@@ -391,16 +395,21 @@
return;
}
+ // Qualified methods are maximally-specific methods
+ // These include public, instance concrete (=default) and abstract methods
GrowableArray<Method*> qualified_methods;
int num_defaults = 0;
int default_index = -1;
+ int qualified_index = -1;
for (int i = 0; i < _members.length(); ++i) {
Pair<Method*,QualifiedState> entry = _members.at(i);
if (entry.second == QUALIFIED) {
qualified_methods.append(entry.first);
- default_index++;
+ qualified_index++;
if (entry.first->is_default_method()) {
num_defaults++;
+ default_index = qualified_index;
+
}
}
}
@@ -408,16 +417,10 @@
if (qualified_methods.length() == 0) {
_exception_message = generate_no_defaults_message(CHECK);
_exception_name = vmSymbols::java_lang_AbstractMethodError();
- } else if (qualified_methods.length() == 1) {
- // leave abstract methods alone, they will be found via normal search path
- Method* method = qualified_methods.at(0);
- if (!method->is_abstract()) {
- _selected_target = qualified_methods.at(0);
- }
- // If only one qualified method is default, select that
+ // If only one qualified method is default, select that
} else if (num_defaults == 1) {
_selected_target = qualified_methods.at(default_index);
- } else {
+ } else if (num_defaults > 1) {
_exception_message = generate_conflicts_message(&qualified_methods,CHECK);
_exception_name = vmSymbols::java_lang_IncompatibleClassChangeError();
if (TraceDefaultMethods) {
@@ -425,6 +428,7 @@
tty->print_cr("");
}
}
+ // leave abstract methods alone, they will be found via normal search path
}
bool contains_signature(Symbol* query) {
@@ -704,8 +708,10 @@
Method* m = iklass->find_method(_method_name, _method_signature);
// private interface methods are not candidates for default methods
// invokespecial to private interface methods doesn't use default method logic
+ // The overpasses are your supertypes' errors, we do not include them
// future: take access controls into account for superclass methods
- if (m != NULL && !m->is_static() && (!iklass->is_interface() || m->is_public())) {
+ if (m != NULL && !m->is_static() && !m->is_overpass() &&
+ (!iklass->is_interface() || m->is_public())) {
if (_family == NULL) {
_family = new StatefulMethodFamily();
}
@@ -781,7 +787,8 @@
#ifndef PRODUCT
if (TraceDefaultMethods) {
ResourceMark rm; // be careful with these!
- tty->print_cr("Class %s requires default method processing",
+ tty->print_cr("%s %s requires default method processing",
+ klass->is_interface() ? "Interface" : "Class",
klass->name()->as_klass_external_name());
PrintHierarchy printer;
printer.run(klass);
@@ -806,7 +813,7 @@
}
#ifndef PRODUCT
if (TraceDefaultMethods) {
- tty->print_cr("Creating overpasses...");
+ tty->print_cr("Creating defaults and overpasses...");
}
#endif // ndef PRODUCT
@@ -1076,7 +1083,9 @@
klass->set_initial_method_idnum(new_size);
ClassLoaderData* cld = klass->class_loader_data();
- MetadataFactory::free_array(cld, original_methods);
+ if (original_methods ->length() > 0) {
+ MetadataFactory::free_array(cld, original_methods);
+ }
if (original_ordering->length() > 0) {
klass->set_method_ordering(merged_ordering);
MetadataFactory::free_array(cld, original_ordering);