提交 24d75b99 编写于 作者: L lfoltan

8036805: Correct linker method lookup.

Summary: Correct handling of array of primitive type qualifiers during field and method resolution.
Reviewed-by: acorn, hseigel, ahgross
上级 e459d2a8
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -245,6 +245,12 @@ void LinkResolver::resolve_klass(KlassHandle& result, constantPoolHandle pool, i ...@@ -245,6 +245,12 @@ void LinkResolver::resolve_klass(KlassHandle& result, constantPoolHandle pool, i
void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, bool in_imethod_resolve, TRAPS) { void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, bool in_imethod_resolve, TRAPS) {
Method* result_oop = klass->uncached_lookup_method(name, signature); Method* result_oop = klass->uncached_lookup_method(name, signature);
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.
...@@ -283,6 +289,11 @@ void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, Klass ...@@ -283,6 +289,11 @@ void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, Klass
result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature)); result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature));
} }
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) {
...@@ -539,7 +550,7 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res ...@@ -539,7 +550,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);
...@@ -552,16 +563,16 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res ...@@ -552,16 +563,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. check if method is concrete // 5. check if method is concrete
...@@ -636,17 +647,18 @@ void LinkResolver::resolve_interface_method(methodHandle& resolved_method, ...@@ -636,17 +647,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 (nostatics && resolved_method->is_static()) { if (nostatics && resolved_method->is_static()) {
...@@ -779,7 +791,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, KlassHandle resolved_klass ...@@ -779,7 +791,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);
......
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -64,6 +64,13 @@ oop ArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) { ...@@ -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) const { Method* ArrayKlass::uncached_lookup_method(Symbol* name, Symbol* signature) 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");
......
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -28,6 +28,7 @@ ...@@ -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
...@@ -85,6 +86,9 @@ class ArrayKlass: public Klass { ...@@ -85,6 +86,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) const; Method* uncached_lookup_method(Symbol* name, Symbol* signature) const;
......
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -128,6 +128,15 @@ bool Klass::compute_is_subtype_of(Klass* k) { ...@@ -128,6 +128,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) const { Method* Klass::uncached_lookup_method(Symbol* name, Symbol* signature) const {
#ifdef ASSERT #ifdef ASSERT
......
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -91,6 +91,7 @@ class ClassLoaderData; ...@@ -91,6 +91,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;
...@@ -421,6 +422,7 @@ class Klass : public Metadata { ...@@ -421,6 +422,7 @@ class Klass : public Metadata {
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) const; virtual Method* uncached_lookup_method(Symbol* name, Symbol* signature) const;
public: public:
Method* lookup_method(Symbol* name, Symbol* signature) const { Method* lookup_method(Symbol* name, Symbol* signature) const {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册