Mon, 16 Dec 2013 08:24:33 -0500
8027804: JCK resolveMethod test fails expecting AbstractMethodError
Summary: Create AME overpass methods and fix method search logic
Reviewed-by: kamg, acorn, lfoltan, coleenp
1.1 --- a/src/share/vm/classfile/defaultMethods.cpp Fri Dec 13 09:48:29 2013 -0800 1.2 +++ b/src/share/vm/classfile/defaultMethods.cpp Mon Dec 16 08:24:33 2013 -0500 1.3 @@ -349,6 +349,7 @@ 1.4 } 1.5 1.6 Symbol* generate_no_defaults_message(TRAPS) const; 1.7 + Symbol* generate_method_message(Symbol *klass_name, Method* method, TRAPS) const; 1.8 Symbol* generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const; 1.9 1.10 public: 1.11 @@ -414,21 +415,25 @@ 1.12 } 1.13 } 1.14 1.15 - if (qualified_methods.length() == 0) { 1.16 - _exception_message = generate_no_defaults_message(CHECK); 1.17 + if (num_defaults == 0) { 1.18 + if (qualified_methods.length() == 0) { 1.19 + _exception_message = generate_no_defaults_message(CHECK); 1.20 + } else { 1.21 + assert(root != NULL, "Null root class"); 1.22 + _exception_message = generate_method_message(root->name(), qualified_methods.at(0), CHECK); 1.23 + } 1.24 _exception_name = vmSymbols::java_lang_AbstractMethodError(); 1.25 // If only one qualified method is default, select that 1.26 } else if (num_defaults == 1) { 1.27 _selected_target = qualified_methods.at(default_index); 1.28 } else if (num_defaults > 1) { 1.29 - _exception_message = generate_conflicts_message(&qualified_methods,CHECK); 1.30 - _exception_name = vmSymbols::java_lang_IncompatibleClassChangeError(); 1.31 + _exception_message = generate_conflicts_message(&qualified_methods,CHECK); 1.32 + _exception_name = vmSymbols::java_lang_IncompatibleClassChangeError(); 1.33 if (TraceDefaultMethods) { 1.34 _exception_message->print_value_on(tty); 1.35 tty->print_cr(""); 1.36 } 1.37 } 1.38 - // leave abstract methods alone, they will be found via normal search path 1.39 } 1.40 1.41 bool contains_signature(Symbol* query) { 1.42 @@ -486,6 +491,19 @@ 1.43 return SymbolTable::new_symbol("No qualifying defaults found", CHECK_NULL); 1.44 } 1.45 1.46 +Symbol* MethodFamily::generate_method_message(Symbol *klass_name, Method* method, TRAPS) const { 1.47 + stringStream ss; 1.48 + ss.print("Method "); 1.49 + Symbol* name = method->name(); 1.50 + Symbol* signature = method->signature(); 1.51 + ss.write((const char*)klass_name->bytes(), klass_name->utf8_length()); 1.52 + ss.print("."); 1.53 + ss.write((const char*)name->bytes(), name->utf8_length()); 1.54 + ss.write((const char*)signature->bytes(), signature->utf8_length()); 1.55 + ss.print(" is abstract"); 1.56 + return SymbolTable::new_symbol(ss.base(), (int)ss.size(), CHECK_NULL); 1.57 +} 1.58 + 1.59 Symbol* MethodFamily::generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const { 1.60 stringStream ss; 1.61 ss.print("Conflicting default methods:");
2.1 --- a/src/share/vm/interpreter/linkResolver.cpp Fri Dec 13 09:48:29 2013 -0800 2.2 +++ b/src/share/vm/interpreter/linkResolver.cpp Mon Dec 16 08:24:33 2013 -0500 2.3 @@ -300,7 +300,7 @@ 2.4 Symbol* signature = resolved_method->signature(); 2.5 2.6 // First check in default method array 2.7 - if (!resolved_method->is_abstract() && 2.8 + if (!resolved_method->is_abstract() && 2.9 (InstanceKlass::cast(klass())->default_methods() != NULL)) { 2.10 int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), name, signature); 2.11 if (index >= 0 ) { 2.12 @@ -318,7 +318,11 @@ 2.13 2.14 void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { 2.15 InstanceKlass *ik = InstanceKlass::cast(klass()); 2.16 - result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name, signature)); 2.17 + 2.18 + // Specify 'true' in order to skip default methods when searching the 2.19 + // interfaces. Function lookup_method_in_klasses() already looked for 2.20 + // the method in the default methods table. 2.21 + result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name, signature, true)); 2.22 } 2.23 2.24 void LinkResolver::lookup_polymorphic_method(methodHandle& result, 2.25 @@ -620,7 +624,7 @@ 2.26 bool check_access, 2.27 bool nostatics, TRAPS) { 2.28 2.29 - // check if klass is interface 2.30 + // check if klass is interface 2.31 if (!resolved_klass->is_interface()) { 2.32 ResourceMark rm(THREAD); 2.33 char buf[200]; 2.34 @@ -1287,8 +1291,11 @@ 2.35 resolved_klass()->external_name()); 2.36 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); 2.37 } 2.38 + 2.39 // do lookup based on receiver klass 2.40 methodHandle sel_method; 2.41 + // This search must match the linktime preparation search for itable initialization 2.42 + // to correctly enforce loader constraints for interface method inheritance 2.43 lookup_instance_method_in_klasses(sel_method, recv_klass, 2.44 resolved_method->name(), 2.45 resolved_method->signature(), CHECK);
3.1 --- a/src/share/vm/oops/instanceKlass.cpp Fri Dec 13 09:48:29 2013 -0800 3.2 +++ b/src/share/vm/oops/instanceKlass.cpp Mon Dec 16 08:24:33 2013 -0500 3.3 @@ -1498,13 +1498,18 @@ 3.4 return -1; 3.5 } 3.6 3.7 -// lookup_method searches both the local methods array and all superclasses methods arrays 3.8 +// uncached_lookup_method searches both the local class methods array and all 3.9 +// superclasses methods arrays, skipping any overpass methods in superclasses. 3.10 Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature) const { 3.11 Klass* klass = const_cast<InstanceKlass*>(this); 3.12 + bool dont_ignore_overpasses = true; // For the class being searched, find its overpasses. 3.13 while (klass != NULL) { 3.14 Method* method = InstanceKlass::cast(klass)->find_method(name, signature); 3.15 - if (method != NULL) return method; 3.16 + if ((method != NULL) && (dont_ignore_overpasses || !method->is_overpass())) { 3.17 + return method; 3.18 + } 3.19 klass = InstanceKlass::cast(klass)->super(); 3.20 + dont_ignore_overpasses = false; // Ignore overpass methods in all superclasses. 3.21 } 3.22 return NULL; 3.23 } 3.24 @@ -1519,7 +1524,7 @@ 3.25 } 3.26 // Look up interfaces 3.27 if (m == NULL) { 3.28 - m = lookup_method_in_all_interfaces(name, signature); 3.29 + m = lookup_method_in_all_interfaces(name, signature, false); 3.30 } 3.31 return m; 3.32 } 3.33 @@ -1528,14 +1533,16 @@ 3.34 // Do NOT return private or static methods, new in JDK8 which are not externally visible 3.35 // They should only be found in the initial InterfaceMethodRef 3.36 Method* InstanceKlass::lookup_method_in_all_interfaces(Symbol* name, 3.37 - Symbol* signature) const { 3.38 + Symbol* signature, 3.39 + bool skip_default_methods) const { 3.40 Array<Klass*>* all_ifs = transitive_interfaces(); 3.41 int num_ifs = all_ifs->length(); 3.42 InstanceKlass *ik = NULL; 3.43 for (int i = 0; i < num_ifs; i++) { 3.44 ik = InstanceKlass::cast(all_ifs->at(i)); 3.45 Method* m = ik->lookup_method(name, signature); 3.46 - if (m != NULL && m->is_public() && !m->is_static()) { 3.47 + if (m != NULL && m->is_public() && !m->is_static() && 3.48 + (!skip_default_methods || !m->is_default_method())) { 3.49 return m; 3.50 } 3.51 }
4.1 --- a/src/share/vm/oops/instanceKlass.hpp Fri Dec 13 09:48:29 2013 -0800 4.2 +++ b/src/share/vm/oops/instanceKlass.hpp Mon Dec 16 08:24:33 2013 -0500 4.3 @@ -525,7 +525,8 @@ 4.4 4.5 // lookup a method in all the interfaces that this class implements 4.6 // (returns NULL if not found) 4.7 - Method* lookup_method_in_all_interfaces(Symbol* name, Symbol* signature) const; 4.8 + Method* lookup_method_in_all_interfaces(Symbol* name, Symbol* signature, bool skip_default_methods) const; 4.9 + 4.10 // lookup a method in local defaults then in all interfaces 4.11 // (returns NULL if not found) 4.12 Method* lookup_method_in_ordered_interfaces(Symbol* name, Symbol* signature) const;
5.1 --- a/src/share/vm/oops/klassVtable.cpp Fri Dec 13 09:48:29 2013 -0800 5.2 +++ b/src/share/vm/oops/klassVtable.cpp Mon Dec 16 08:24:33 2013 -0500 5.3 @@ -622,7 +622,7 @@ 5.4 // this check for all access permissions. 5.5 InstanceKlass *sk = InstanceKlass::cast(super); 5.6 if (sk->has_miranda_methods()) { 5.7 - if (sk->lookup_method_in_all_interfaces(name, signature) != NULL) { 5.8 + if (sk->lookup_method_in_all_interfaces(name, signature, false) != NULL) { 5.9 return false; // found a matching miranda; we do not need a new entry 5.10 } 5.11 } 5.12 @@ -743,7 +743,7 @@ 5.13 if (is_miranda(im, class_methods, default_methods, super)) { // is it a miranda at all? 5.14 InstanceKlass *sk = InstanceKlass::cast(super); 5.15 // check if it is a duplicate of a super's miranda 5.16 - if (sk->lookup_method_in_all_interfaces(im->name(), im->signature()) == NULL) { 5.17 + if (sk->lookup_method_in_all_interfaces(im->name(), im->signature(), false) == NULL) { 5.18 new_mirandas->append(im); 5.19 } 5.20 if (all_mirandas != NULL) { 5.21 @@ -1085,6 +1085,8 @@ 5.22 Method* m = methods->at(i); 5.23 methodHandle target; 5.24 if (m->has_itable_index()) { 5.25 + // This search must match the runtime resolution, i.e. selection search for invokeinterface 5.26 + // to correctly enforce loader constraints for interface method inheritance 5.27 LinkResolver::lookup_instance_method_in_klasses(target, _klass, m->name(), m->signature(), CHECK); 5.28 } 5.29 if (target == NULL || !target->is_public() || target->is_abstract()) {