diff --git a/src/share/vm/classfile/defaultMethods.cpp b/src/share/vm/classfile/defaultMethods.cpp index 619856d69e5a5dbb0719d0a3ee53d8a6c2b2b7eb..129eecbad3b89cd1ec11eed8296968b1de9509f1 100644 --- a/src/share/vm/classfile/defaultMethods.cpp +++ b/src/share/vm/classfile/defaultMethods.cpp @@ -625,13 +625,13 @@ static GrowableArray* find_empty_vtable_slots( while (super != NULL) { for (int i = 0; i < super->methods()->length(); ++i) { Method* m = super->methods()->at(i); - if (m->is_overpass()) { + if (m->is_overpass() || m->is_static()) { // m is a method that would have been a miranda if not for the // default method processing that occurred on behalf of our superclass, // so it's a method we want to re-examine in this new context. That is, // unless we have a real implementation of it in the current class. Method* impl = klass->lookup_method(m->name(), m->signature()); - if (impl == NULL || impl->is_overpass()) { + if (impl == NULL || impl->is_overpass() || impl->is_static()) { if (!already_in_vtable_slots(slots, m)) { slots->append(new EmptyVtableSlot(m)); } @@ -648,7 +648,7 @@ static GrowableArray* find_empty_vtable_slots( // so it's a method we want to re-examine in this new context. That is, // unless we have a real implementation of it in the current class. Method* impl = klass->lookup_method(m->name(), m->signature()); - if (impl == NULL || impl->is_overpass()) { + if (impl == NULL || impl->is_overpass() || impl->is_static()) { if (!already_in_vtable_slots(slots, m)) { slots->append(new EmptyVtableSlot(m)); } diff --git a/src/share/vm/interpreter/linkResolver.cpp b/src/share/vm/interpreter/linkResolver.cpp index 9ca57ce5fad4595ec428373dc7929f4042893aa4..573ccc1cf62df55b9534b18e8e46784862ba77a2 100644 --- a/src/share/vm/interpreter/linkResolver.cpp +++ b/src/share/vm/interpreter/linkResolver.cpp @@ -267,8 +267,8 @@ void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, Klass Method* result_oop = klass->uncached_lookup_method(name, signature); result = methodHandle(THREAD, result_oop); while (!result.is_null() && result->is_static() && result->method_holder()->super() != NULL) { - klass = KlassHandle(THREAD, result->method_holder()->super()); - result = methodHandle(THREAD, klass->uncached_lookup_method(name, signature)); + KlassHandle super_klass = KlassHandle(THREAD, result->method_holder()->super()); + result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature)); } if (result.is_null()) { diff --git a/src/share/vm/oops/instanceKlass.cpp b/src/share/vm/oops/instanceKlass.cpp index 5077f123e38c50dd961fc05c216d0232b4da0c70..3075a13430781e661469f8666958ad981563d112 100644 --- a/src/share/vm/oops/instanceKlass.cpp +++ b/src/share/vm/oops/instanceKlass.cpp @@ -1427,6 +1427,17 @@ Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const { return InstanceKlass::find_method(methods(), name, signature); } +// find_instance_method looks up the name/signature in the local methods array +// and skips over static methods +Method* InstanceKlass::find_instance_method( + Array* methods, Symbol* name, Symbol* signature) { + Method* meth = InstanceKlass::find_method(methods, name, signature); + if (meth != NULL && meth->is_static()) { + meth = NULL; + } + return meth; +} + // find_method looks up the name/signature in the local methods array Method* InstanceKlass::find_method( Array* methods, Symbol* name, Symbol* signature) { diff --git a/src/share/vm/oops/instanceKlass.hpp b/src/share/vm/oops/instanceKlass.hpp index c667f2c2d12dae9a9dcc78ffcf3319d83e9a4135..84cc0046a95a4627f4faa74f523b0b517c1aa82e 100644 --- a/src/share/vm/oops/instanceKlass.hpp +++ b/src/share/vm/oops/instanceKlass.hpp @@ -515,6 +515,7 @@ class InstanceKlass: public Klass { // find a local method (returns NULL if not found) Method* find_method(Symbol* name, Symbol* signature) const; static Method* find_method(Array* methods, Symbol* name, Symbol* signature); + static Method* find_instance_method(Array* methods, Symbol* name, Symbol* signature); // find a local method index in default_methods (returns -1 if not found) static int find_method_index(Array* methods, Symbol* name, Symbol* signature); diff --git a/src/share/vm/oops/klassVtable.cpp b/src/share/vm/oops/klassVtable.cpp index 1399a41baa8dc6956b89c546eb264277c8b2d0d1..509c78853607fcf78327982c9f1feb1322f15c58 100644 --- a/src/share/vm/oops/klassVtable.cpp +++ b/src/share/vm/oops/klassVtable.cpp @@ -665,6 +665,11 @@ bool klassVtable::is_miranda_entry_at(int i) { // check if a method is a miranda method, given a class's methods table, // its default_method table and its super +// Miranda methods are calculated twice: +// first: before vtable size calculation: including abstract and default +// This is seen by default method creation +// Second: recalculated during vtable initialization: only abstract +// This is seen by link resolution and selection. // "miranda" means not static, not defined by this class. // private methods in interfaces do not belong in the miranda list. // the caller must make sure that the method belongs to an interface implemented by the class @@ -678,7 +683,8 @@ bool klassVtable::is_miranda(Method* m, Array* class_methods, } Symbol* name = m->name(); Symbol* signature = m->signature(); - if (InstanceKlass::find_method(class_methods, name, signature) == NULL) { + + if (InstanceKlass::find_instance_method(class_methods, name, signature) == NULL) { // did not find it in the method table of the current class if ((default_methods == NULL) || InstanceKlass::find_method(default_methods, name, signature) == NULL) { @@ -688,6 +694,12 @@ bool klassVtable::is_miranda(Method* m, Array* class_methods, } Method* mo = InstanceKlass::cast(super)->lookup_method(name, signature); + while (mo != NULL && mo->access_flags().is_static() + && mo->method_holder() != NULL + && mo->method_holder()->super() != NULL) + { + mo = mo->method_holder()->super()->uncached_lookup_method(name, signature); + } if (mo == NULL || mo->access_flags().is_private() ) { // super class hierarchy does not implement it or protection is different return true;