src/share/vm/interpreter/linkResolver.cpp

changeset 4245
4735d2c84362
parent 4133
f6b0eb4e44cf
child 4251
18fb7da42534
     1.1 --- a/src/share/vm/interpreter/linkResolver.cpp	Thu Nov 01 13:05:47 2012 +0100
     1.2 +++ b/src/share/vm/interpreter/linkResolver.cpp	Thu Oct 11 12:25:42 2012 -0400
     1.3 @@ -23,6 +23,7 @@
     1.4   */
     1.5  
     1.6  #include "precompiled.hpp"
     1.7 +#include "classfile/defaultMethods.hpp"
     1.8  #include "classfile/systemDictionary.hpp"
     1.9  #include "classfile/vmSymbols.hpp"
    1.10  #include "compiler/compileBroker.hpp"
    1.11 @@ -404,21 +405,13 @@
    1.12                                    Symbol* method_name, Symbol* method_signature,
    1.13                                    KlassHandle current_klass, bool check_access, TRAPS) {
    1.14  
    1.15 -  // 1. check if klass is not interface
    1.16 -  if (resolved_klass->is_interface()) {
    1.17 -    ResourceMark rm(THREAD);
    1.18 -    char buf[200];
    1.19 -    jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected", Klass::cast(resolved_klass())->external_name());
    1.20 -    THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
    1.21 -  }
    1.22 -
    1.23    Handle nested_exception;
    1.24  
    1.25 -  // 2. lookup method in resolved klass and its super klasses
    1.26 +  // 1. lookup method in resolved klass and its super klasses
    1.27    lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK);
    1.28  
    1.29    if (resolved_method.is_null()) { // not found in the class hierarchy
    1.30 -    // 3. lookup method in all the interfaces implemented by the resolved klass
    1.31 +    // 2. lookup method in all the interfaces implemented by the resolved klass
    1.32      lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
    1.33  
    1.34      if (resolved_method.is_null()) {
    1.35 @@ -432,7 +425,7 @@
    1.36      }
    1.37  
    1.38      if (resolved_method.is_null()) {
    1.39 -      // 4. method lookup failed
    1.40 +      // 3. method lookup failed
    1.41        ResourceMark rm(THREAD);
    1.42        THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(),
    1.43                        Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
    1.44 @@ -442,6 +435,15 @@
    1.45      }
    1.46    }
    1.47  
    1.48 +  // 4. check if klass is not interface
    1.49 +  if (resolved_klass->is_interface() && resolved_method->is_abstract()) {
    1.50 +    ResourceMark rm(THREAD);
    1.51 +    char buf[200];
    1.52 +    jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected",
    1.53 +        resolved_klass()->external_name());
    1.54 +    THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
    1.55 +  }
    1.56 +
    1.57    // 5. check if method is concrete
    1.58    if (resolved_method->is_abstract() && !resolved_klass->is_abstract()) {
    1.59      ResourceMark rm(THREAD);
    1.60 @@ -743,6 +745,27 @@
    1.61                                                     Symbol* method_name, Symbol* method_signature,
    1.62                                                     KlassHandle current_klass, bool check_access, TRAPS) {
    1.63  
    1.64 +  if (resolved_klass->is_interface() && current_klass() != NULL) {
    1.65 +    // If the target class is a direct interface, treat this as a "super"
    1.66 +    // default call.
    1.67 +    //
    1.68 +    // If the current method is an overpass that happens to call a direct
    1.69 +    // super-interface's method, then we'll end up rerunning the default method
    1.70 +    // analysis even though we don't need to, but that's ok since it will end
    1.71 +    // up with the same answer.
    1.72 +    InstanceKlass* ik = InstanceKlass::cast(current_klass());
    1.73 +    Array<Klass*>* interfaces = ik->local_interfaces();
    1.74 +    int num_interfaces = interfaces->length();
    1.75 +    for (int index = 0; index < num_interfaces; index++) {
    1.76 +      if (interfaces->at(index) == resolved_klass()) {
    1.77 +        Method* method = DefaultMethods::find_super_default(current_klass(),
    1.78 +            resolved_klass(), method_name, method_signature, CHECK);
    1.79 +        resolved_method = methodHandle(THREAD, method);
    1.80 +        return;
    1.81 +      }
    1.82 +    }
    1.83 +  }
    1.84 +
    1.85    resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
    1.86  
    1.87    // check if method name is <init>, that it is found in same klass as static type
    1.88 @@ -784,11 +807,17 @@
    1.89    { KlassHandle method_klass  = KlassHandle(THREAD,
    1.90                                              resolved_method->method_holder());
    1.91  
    1.92 -    if (check_access &&
    1.93 +    const bool direct_calling_default_method =
    1.94 +      resolved_klass() != NULL && resolved_method() != NULL &&
    1.95 +      resolved_klass->is_interface() && !resolved_method->is_abstract();
    1.96 +
    1.97 +    if (!direct_calling_default_method &&
    1.98 +        check_access &&
    1.99          // a) check if ACC_SUPER flag is set for the current class
   1.100          current_klass->is_super() &&
   1.101          // b) check if the method class is a superclass of the current class (superclass relation is not reflexive!)
   1.102 -        current_klass->is_subtype_of(method_klass()) && current_klass() != method_klass() &&
   1.103 +        current_klass->is_subtype_of(method_klass()) &&
   1.104 +        current_klass() != method_klass() &&
   1.105          // c) check if the method is not <init>
   1.106          resolved_method->name() != vmSymbols::object_initializer_name()) {
   1.107        // Lookup super method

mercurial