From edc10143cb71052df6b6dc2ff8dd23f0a12a976f Mon Sep 17 00:00:00 2001 From: Lois Foltan Date: Wed, 7 May 2014 19:38:22 +0400 Subject: [PATCH] 8036805: Correct linker method lookup Correct handling of array of primitive type qualifiers during field and method resolution. Reviewed-by: acorn, hseigel, ahgross --- .../src/share/vm/interpreter/linkResolver.cpp | 52 ++++++++++++------- hotspot/src/share/vm/oops/arrayKlass.cpp | 7 +++ hotspot/src/share/vm/oops/arrayKlass.hpp | 4 ++ hotspot/src/share/vm/oops/klass.cpp | 9 ++++ hotspot/src/share/vm/oops/klass.hpp | 2 + 5 files changed, 54 insertions(+), 20 deletions(-) diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp index 6fbb3bfa6f1..5bf368a1765 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp @@ -246,6 +246,12 @@ void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle kl // Ignore overpasses so statics can be found during resolution Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::skip_overpass); + if (klass->oop_is_array()) { + // Only consider klass and super klass for arrays + result = methodHandle(THREAD, result_oop); + return; + } + // JDK 8, JVMS 5.4.3.4: Interface method resolution should // ignore static and non-public methods of java.lang.Object, // like clone, finalize, registerNatives. @@ -290,6 +296,11 @@ void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, Klass result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature, Klass::normal)); } + if (klass->oop_is_array()) { + // Only consider klass and super klass for arrays + return; + } + if (result.is_null()) { Array* default_methods = InstanceKlass::cast(klass())->default_methods(); if (default_methods != NULL) { @@ -545,7 +556,7 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res // 2. lookup method in resolved klass and its super klasses lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, true, false, CHECK); - if (resolved_method.is_null()) { // not found in the class hierarchy + if (resolved_method.is_null() && !resolved_klass->oop_is_array()) { // not found in the class hierarchy // 3. lookup method in all the interfaces implemented by the resolved klass lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); @@ -558,16 +569,16 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res CLEAR_PENDING_EXCEPTION; } } + } - if (resolved_method.is_null()) { - // 4. method lookup failed - ResourceMark rm(THREAD); - THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(), - Method::name_and_sig_as_C_string(resolved_klass(), - method_name, - method_signature), - nested_exception); - } + if (resolved_method.is_null()) { + // 4. method lookup failed + ResourceMark rm(THREAD); + THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(), + Method::name_and_sig_as_C_string(resolved_klass(), + method_name, + method_signature), + nested_exception); } // 5. access checks, access checking may be turned off when calling from within the VM. @@ -633,17 +644,18 @@ void LinkResolver::resolve_interface_method(methodHandle& resolved_method, // JDK8: also look for static methods lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, false, true, CHECK); - if (resolved_method.is_null()) { + if (resolved_method.is_null() && !resolved_klass->oop_is_array()) { // lookup method in all the super-interfaces lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); - if (resolved_method.is_null()) { - // no method found - ResourceMark rm(THREAD); - THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(), - Method::name_and_sig_as_C_string(resolved_klass(), - method_name, - method_signature)); - } + } + + if (resolved_method.is_null()) { + // no method found + ResourceMark rm(THREAD); + THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(), + Method::name_and_sig_as_C_string(resolved_klass(), + method_name, + method_signature)); } if (check_access) { @@ -775,7 +787,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, KlassHandle resolved_klass } // Resolve instance field - KlassHandle sel_klass(THREAD, InstanceKlass::cast(resolved_klass())->find_field(field, sig, &fd)); + KlassHandle sel_klass(THREAD, resolved_klass->find_field(field, sig, &fd)); // check if field exists; i.e., if a klass containing the field def has been selected if (sel_klass.is_null()) { ResourceMark rm(THREAD); diff --git a/hotspot/src/share/vm/oops/arrayKlass.cpp b/hotspot/src/share/vm/oops/arrayKlass.cpp index 21de8cb42cf..740ae166adf 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.cpp +++ b/hotspot/src/share/vm/oops/arrayKlass.cpp @@ -64,6 +64,13 @@ oop ArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) { return NULL; } +// find field according to JVM spec 5.4.3.2, returns the klass in which the field is defined +Klass* ArrayKlass::find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const { + // There are no fields in an array klass but look to the super class (Object) + assert(super(), "super klass must be present"); + return super()->find_field(name, sig, fd); +} + Method* ArrayKlass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const { // There are no methods in an array klass but the super class (Object) has some assert(super(), "super klass must be present"); diff --git a/hotspot/src/share/vm/oops/arrayKlass.hpp b/hotspot/src/share/vm/oops/arrayKlass.hpp index 39ae5768aaf..248fde0373a 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.hpp +++ b/hotspot/src/share/vm/oops/arrayKlass.hpp @@ -28,6 +28,7 @@ #include "memory/universe.hpp" #include "oops/klass.hpp" +class fieldDescriptor; class klassVtable; // ArrayKlass is the abstract baseclass for all array classes @@ -77,6 +78,9 @@ class ArrayKlass: public Klass { virtual oop multi_allocate(int rank, jint* sizes, TRAPS); objArrayOop allocate_arrayArray(int n, int length, TRAPS); + // find field according to JVM spec 5.4.3.2, returns the klass in which the field is defined + Klass* find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const; + // Lookup operations Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const; diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index 810c8d729cd..bdd4839be46 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -130,6 +130,15 @@ bool Klass::compute_is_subtype_of(Klass* k) { return is_subclass_of(k); } +Klass* Klass::find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const { +#ifdef ASSERT + tty->print_cr("Error: find_field called on a klass oop." + " Likely error: reflection method does not correctly" + " wrap return value in a mirror object."); +#endif + ShouldNotReachHere(); + return NULL; +} Method* Klass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const { #ifdef ASSERT diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index 5af2104e594..fd7691462f3 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -62,6 +62,7 @@ class ClassLoaderData; class klassVtable; class ParCompactionManager; class KlassSizeStats; +class fieldDescriptor; class Klass : public Metadata { friend class VMStructs; @@ -411,6 +412,7 @@ protected: virtual void initialize(TRAPS); // lookup operation for MethodLookupCache friend class MethodLookupCache; + virtual Klass* find_field(Symbol* name, Symbol* signature, fieldDescriptor* fd) const; virtual Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const; public: Method* lookup_method(Symbol* name, Symbol* signature) const {