8036805: Correct linker method lookup
Correct handling of array of primitive type qualifiers during field and method resolution. Reviewed-by: acorn, hseigel, ahgross
This commit is contained in:
parent
f8d533e6b6
commit
edc10143cb
@ -246,6 +246,12 @@ void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle kl
|
|||||||
// Ignore overpasses so statics can be found during resolution
|
// Ignore overpasses so statics can be found during resolution
|
||||||
Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::skip_overpass);
|
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
|
// JDK 8, JVMS 5.4.3.4: Interface method resolution should
|
||||||
// ignore static and non-public methods of java.lang.Object,
|
// ignore static and non-public methods of java.lang.Object,
|
||||||
// like clone, finalize, registerNatives.
|
// 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));
|
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()) {
|
if (result.is_null()) {
|
||||||
Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods();
|
Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods();
|
||||||
if (default_methods != NULL) {
|
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
|
// 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);
|
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
|
// 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);
|
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;
|
CLEAR_PENDING_EXCEPTION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (resolved_method.is_null()) {
|
if (resolved_method.is_null()) {
|
||||||
// 4. method lookup failed
|
// 4. method lookup failed
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(),
|
THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(),
|
||||||
Method::name_and_sig_as_C_string(resolved_klass(),
|
Method::name_and_sig_as_C_string(resolved_klass(),
|
||||||
method_name,
|
method_name,
|
||||||
method_signature),
|
method_signature),
|
||||||
nested_exception);
|
nested_exception);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. access checks, access checking may be turned off when calling from within the VM.
|
// 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
|
// JDK8: also look for static methods
|
||||||
lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, false, true, CHECK);
|
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 all the super-interfaces
|
||||||
lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
|
lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
|
||||||
if (resolved_method.is_null()) {
|
}
|
||||||
// no method found
|
|
||||||
ResourceMark rm(THREAD);
|
if (resolved_method.is_null()) {
|
||||||
THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(),
|
// no method found
|
||||||
Method::name_and_sig_as_C_string(resolved_klass(),
|
ResourceMark rm(THREAD);
|
||||||
method_name,
|
THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(),
|
||||||
method_signature));
|
Method::name_and_sig_as_C_string(resolved_klass(),
|
||||||
}
|
method_name,
|
||||||
|
method_signature));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_access) {
|
if (check_access) {
|
||||||
@ -775,7 +787,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, KlassHandle resolved_klass
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resolve instance field
|
// 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
|
// check if field exists; i.e., if a klass containing the field def has been selected
|
||||||
if (sel_klass.is_null()) {
|
if (sel_klass.is_null()) {
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
|
@ -64,6 +64,13 @@ oop ArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) {
|
|||||||
return NULL;
|
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 {
|
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
|
// There are no methods in an array klass but the super class (Object) has some
|
||||||
assert(super(), "super klass must be present");
|
assert(super(), "super klass must be present");
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "memory/universe.hpp"
|
#include "memory/universe.hpp"
|
||||||
#include "oops/klass.hpp"
|
#include "oops/klass.hpp"
|
||||||
|
|
||||||
|
class fieldDescriptor;
|
||||||
class klassVtable;
|
class klassVtable;
|
||||||
|
|
||||||
// ArrayKlass is the abstract baseclass for all array classes
|
// 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);
|
virtual oop multi_allocate(int rank, jint* sizes, TRAPS);
|
||||||
objArrayOop allocate_arrayArray(int n, int length, 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
|
// Lookup operations
|
||||||
Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const;
|
Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const;
|
||||||
|
|
||||||
|
@ -130,6 +130,15 @@ bool Klass::compute_is_subtype_of(Klass* k) {
|
|||||||
return is_subclass_of(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 {
|
Method* Klass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const {
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
@ -62,6 +62,7 @@ class ClassLoaderData;
|
|||||||
class klassVtable;
|
class klassVtable;
|
||||||
class ParCompactionManager;
|
class ParCompactionManager;
|
||||||
class KlassSizeStats;
|
class KlassSizeStats;
|
||||||
|
class fieldDescriptor;
|
||||||
|
|
||||||
class Klass : public Metadata {
|
class Klass : public Metadata {
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
@ -411,6 +412,7 @@ protected:
|
|||||||
virtual void initialize(TRAPS);
|
virtual void initialize(TRAPS);
|
||||||
// lookup operation for MethodLookupCache
|
// lookup operation for MethodLookupCache
|
||||||
friend class 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;
|
virtual Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const;
|
||||||
public:
|
public:
|
||||||
Method* lookup_method(Symbol* name, Symbol* signature) const {
|
Method* lookup_method(Symbol* name, Symbol* signature) const {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user