diff -r f7a77bce0bcf -r 8d2924674592 hotspot/src/share/vm/interpreter/linkResolver.cpp --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Mon Dec 02 11:42:10 2013 +0100 +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Tue Dec 03 08:36:15 2013 -0800 @@ -242,7 +242,7 @@ // Look up method in klasses, including static methods // Then look up local default methods -void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { +void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, TRAPS) { Method* result_oop = klass->uncached_lookup_method(name, signature); if (result_oop == NULL) { Array* default_methods = InstanceKlass::cast(klass())->default_methods(); @@ -251,7 +251,7 @@ } } - if (EnableInvokeDynamic && result_oop != NULL) { + if (checkpolymorphism && EnableInvokeDynamic && result_oop != NULL) { vmIntrinsics::ID iid = result_oop->intrinsic_id(); if (MethodHandles::is_signature_polymorphic(iid)) { // Do not link directly to these. The VM must produce a synthetic one using lookup_polymorphic_method. @@ -503,11 +503,14 @@ } if (code == Bytecodes::_invokeinterface) { - resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK); + resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK); } else if (code == Bytecodes::_invokevirtual) { resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK); + } else if (!resolved_klass->is_interface()) { + resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, false, CHECK); } else { - resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, false, CHECK); + bool nostatics = (code == Bytecodes::_invokestatic) ? false : true; + resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, nostatics, CHECK); } } @@ -528,7 +531,7 @@ } // 2. lookup method in resolved klass and its super klasses - lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK); + lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, true, CHECK); if (resolved_method.is_null()) { // not found in the class hierarchy // 3. lookup method in all the interfaces implemented by the resolved klass @@ -612,7 +615,8 @@ Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, - bool check_access, TRAPS) { + bool check_access, + bool nostatics, TRAPS) { // check if klass is interface if (!resolved_klass->is_interface()) { @@ -623,7 +627,8 @@ } // lookup method in this interface or its super, java.lang.Object - lookup_instance_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK); + // JDK8: also look for static methods + lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, false, CHECK); if (resolved_method.is_null()) { // lookup method in all the super-interfaces @@ -638,6 +643,16 @@ } } + if (nostatics && resolved_method->is_static()) { + ResourceMark rm(THREAD); + char buf[200]; + jio_snprintf(buf, sizeof(buf), "Expected instance not static method %s", Method::name_and_sig_as_C_string(resolved_klass(), + resolved_method->name(), + resolved_method->signature())); + THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); + } + + if (check_access) { // JDK8 adds non-public interface methods, and accessability check requirement assert(current_klass.not_null() , "current_klass should not be null"); @@ -864,7 +879,11 @@ Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS) { - resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK); + if (!resolved_klass->is_interface()) { + resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK); + } else { + resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK); + } assert(resolved_method->name() != vmSymbols::class_initializer_name(), "should have been checked in verifier"); // check if static @@ -898,7 +917,11 @@ // and the selected method is recalculated relative to the direct superclass // superinterface.method, which explicitly does not check shadowing - resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK); + if (!resolved_klass->is_interface()) { + resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK); + } else { + resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, true, CHECK); + } // check if method name is , that it is found in same klass as static type if (resolved_method->name() == vmSymbols::object_initializer_name() && @@ -1219,7 +1242,7 @@ void LinkResolver::linktime_resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS) { // normal interface method resolution - resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); + resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, true, CHECK); assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier"); assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier");