Mercurial > hg > truffle
comparison src/share/vm/interpreter/linkResolver.cpp @ 13436:9fbabcbb875b
8028741: Interface Method Resolution should skip static and non-public methods in j.l.Object
Summary: Implementation of JDK 8 JVMS 5.4.3.4 specification change to skip static and non-public methods of java.lang.Object for interface method resolution.
Reviewed-by: acorn, coleenp
Contributed-by: lois.foltan@oracle.com
author | hseigel |
---|---|
date | Tue, 10 Dec 2013 16:18:26 -0500 |
parents | 769557390c43 |
children | 02f27ecb4f3a 2353011244bd |
comparison
equal
deleted
inserted
replaced
13435:bf15208b72a5 | 13436:9fbabcbb875b |
---|---|
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()) { |