240 // |
240 // |
241 // According to JVM spec. $5.4.3c & $5.4.3d |
241 // According to JVM spec. $5.4.3c & $5.4.3d |
242 |
242 |
243 // Look up method in klasses, including static methods |
243 // Look up method in klasses, including static methods |
244 // Then look up local default methods |
244 // Then look up local default methods |
245 void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, TRAPS) { |
245 void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, bool in_imethod_resolve, TRAPS) { |
246 Method* result_oop = klass->uncached_lookup_method(name, signature); |
246 Method* result_oop = klass->uncached_lookup_method(name, signature); |
|
247 |
|
248 // JDK 8, JVMS 5.4.3.4: Interface method resolution should |
|
249 // ignore static and non-public methods of java.lang.Object, |
|
250 // like clone, finalize, registerNatives. |
|
251 if (in_imethod_resolve && |
|
252 result_oop != NULL && |
|
253 klass->is_interface() && |
|
254 (result_oop->is_static() || !result_oop->is_public()) && |
|
255 result_oop->method_holder() == SystemDictionary::Object_klass()) { |
|
256 result_oop = NULL; |
|
257 } |
|
258 |
247 if (result_oop == NULL) { |
259 if (result_oop == NULL) { |
248 Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods(); |
260 Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods(); |
249 if (default_methods != NULL) { |
261 if (default_methods != NULL) { |
250 result_oop = InstanceKlass::find_method(default_methods, name, signature); |
262 result_oop = InstanceKlass::find_method(default_methods, name, signature); |
251 } |
263 } |
418 methodHandle sel_method, |
430 methodHandle sel_method, |
419 TRAPS) { |
431 TRAPS) { |
420 |
432 |
421 AccessFlags flags = sel_method->access_flags(); |
433 AccessFlags flags = sel_method->access_flags(); |
422 |
434 |
423 // Special case #1: arrays always override "clone". JVMS 2.15. |
435 // Special case: arrays always override "clone". JVMS 2.15. |
424 // If the resolved klass is an array class, and the declaring class |
436 // If the resolved klass is an array class, and the declaring class |
425 // is java.lang.Object and the method is "clone", set the flags |
437 // is java.lang.Object and the method is "clone", set the flags |
426 // to public. |
438 // to public. |
427 // Special case #2: If the resolved klass is an interface, and |
|
428 // the declaring class is java.lang.Object, and the method is |
|
429 // "clone" or "finalize", set the flags to public. If the |
|
430 // resolved interface does not contain "clone" or "finalize" |
|
431 // methods, the method/interface method resolution looks to |
|
432 // the interface's super class, java.lang.Object. With JDK 8 |
|
433 // interface accessability check requirement, special casing |
|
434 // this scenario is necessary to avoid an IAE. |
|
435 // |
439 // |
436 // We'll check for each method name first and then java.lang.Object |
440 // We'll check for the method name first, as that's most likely |
437 // to best short-circuit out of these tests. |
441 // to be false (so we'll short-circuit out of these tests). |
438 if (((sel_method->name() == vmSymbols::clone_name() && |
442 if (sel_method->name() == vmSymbols::clone_name() && |
439 (resolved_klass->oop_is_array() || resolved_klass->is_interface())) || |
443 sel_klass() == SystemDictionary::Object_klass() && |
440 (sel_method->name() == vmSymbols::finalize_method_name() && |
444 resolved_klass->oop_is_array()) { |
441 resolved_klass->is_interface())) && |
|
442 sel_klass() == SystemDictionary::Object_klass()) { |
|
443 // We need to change "protected" to "public". |
445 // We need to change "protected" to "public". |
444 assert(flags.is_protected(), "clone or finalize not protected?"); |
446 assert(flags.is_protected(), "clone not protected?"); |
445 jint new_flags = flags.as_int(); |
447 jint new_flags = flags.as_int(); |
446 new_flags = new_flags & (~JVM_ACC_PROTECTED); |
448 new_flags = new_flags & (~JVM_ACC_PROTECTED); |
447 new_flags = new_flags | JVM_ACC_PUBLIC; |
449 new_flags = new_flags | JVM_ACC_PUBLIC; |
448 flags.set_flags(new_flags); |
450 flags.set_flags(new_flags); |
449 } |
451 } |
529 resolved_klass()->external_name()); |
531 resolved_klass()->external_name()); |
530 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
532 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
531 } |
533 } |
532 |
534 |
533 // 2. lookup method in resolved klass and its super klasses |
535 // 2. lookup method in resolved klass and its super klasses |
534 lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, true, CHECK); |
536 lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, true, false, CHECK); |
535 |
537 |
536 if (resolved_method.is_null()) { // not found in the class hierarchy |
538 if (resolved_method.is_null()) { // not found in the class hierarchy |
537 // 3. lookup method in all the interfaces implemented by the resolved klass |
539 // 3. lookup method in all the interfaces implemented by the resolved klass |
538 lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); |
540 lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); |
539 |
541 |
626 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
628 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
627 } |
629 } |
628 |
630 |
629 // lookup method in this interface or its super, java.lang.Object |
631 // lookup method in this interface or its super, java.lang.Object |
630 // JDK8: also look for static methods |
632 // JDK8: also look for static methods |
631 lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, false, CHECK); |
633 lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, false, true, CHECK); |
632 |
634 |
633 if (resolved_method.is_null()) { |
635 if (resolved_method.is_null()) { |
634 // lookup method in all the super-interfaces |
636 // lookup method in all the super-interfaces |
635 lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); |
637 lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); |
636 if (resolved_method.is_null()) { |
638 if (resolved_method.is_null()) { |