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
|
||||
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<Method*>* 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);
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user