8027804: JCK resolveMethod test fails expecting AbstractMethodError

Mon, 16 Dec 2013 08:24:33 -0500

author
hseigel
date
Mon, 16 Dec 2013 08:24:33 -0500
changeset 6195
5832cdaf89c6
parent 6183
7469c9ca967a
child 6196
62e87648a4be

8027804: JCK resolveMethod test fails expecting AbstractMethodError
Summary: Create AME overpass methods and fix method search logic
Reviewed-by: kamg, acorn, lfoltan, coleenp

src/share/vm/classfile/defaultMethods.cpp file | annotate | diff | comparison | revisions
src/share/vm/interpreter/linkResolver.cpp file | annotate | diff | comparison | revisions
src/share/vm/oops/instanceKlass.cpp file | annotate | diff | comparison | revisions
src/share/vm/oops/instanceKlass.hpp file | annotate | diff | comparison | revisions
src/share/vm/oops/klassVtable.cpp file | annotate | diff | comparison | revisions
     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()) {

mercurial