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