8237766: Enhance signature API to include ResolvingSignatureStream
New ResolvingSignatureStream class provides the capability to easily walk through the differing parts of a signature while resolving or querying its underlying types. Co-authored-by: John Rose <john.r.rose@oracle.com> Reviewed-by: coleenp, fparain, hseigel
This commit is contained in:
parent
e455d382e7
commit
c280d98e80
@ -969,8 +969,7 @@ Klass* SystemDictionary::find_instance_or_array_klass(Symbol* class_name,
|
||||
if (t != T_OBJECT) {
|
||||
k = Universe::typeArrayKlassObj(t);
|
||||
} else {
|
||||
Symbol* obj_class = ss.as_symbol();
|
||||
k = SystemDictionary::find(obj_class, class_loader, protection_domain, THREAD);
|
||||
k = SystemDictionary::find(ss.as_symbol(), class_loader, protection_domain, THREAD);
|
||||
}
|
||||
if (k != NULL) {
|
||||
k = k->array_klass_or_null(ndims);
|
||||
@ -2527,8 +2526,8 @@ static bool is_always_visible_class(oop mirror) {
|
||||
InstanceKlass::cast(klass)->is_same_class_package(SystemDictionary::MethodHandle_klass())); // java.lang.invoke
|
||||
}
|
||||
|
||||
// Find or construct the Java mirror (java.lang.Class instance) for a
|
||||
// for the given field type signature, as interpreted relative to the
|
||||
// Find or construct the Java mirror (java.lang.Class instance) for
|
||||
// the given field type signature, as interpreted relative to the
|
||||
// given class loader. Handles primitives, void, references, arrays,
|
||||
// and all other reflectable types, except method types.
|
||||
// N.B. Code in reflection should use this entry point.
|
||||
@ -2538,57 +2537,33 @@ Handle SystemDictionary::find_java_mirror_for_type(Symbol* signature,
|
||||
Handle protection_domain,
|
||||
SignatureStream::FailureMode failure_mode,
|
||||
TRAPS) {
|
||||
Handle empty;
|
||||
|
||||
assert(accessing_klass == NULL || (class_loader.is_null() && protection_domain.is_null()),
|
||||
"one or the other, or perhaps neither");
|
||||
|
||||
SignatureStream ss(signature, false);
|
||||
|
||||
// What we have here must be a valid field descriptor,
|
||||
// and all valid field descriptors are supported.
|
||||
// Produce the same java.lang.Class that reflection reports.
|
||||
if (ss.is_primitive() || (ss.type() == T_VOID)) {
|
||||
|
||||
// It's a primitive. (Void has a primitive mirror too.)
|
||||
return Handle(THREAD, java_lang_Class::primitive_mirror(ss.type()));
|
||||
|
||||
} else if (ss.is_reference()) {
|
||||
|
||||
// It's a reference type.
|
||||
if (accessing_klass != NULL) {
|
||||
class_loader = Handle(THREAD, accessing_klass->class_loader());
|
||||
protection_domain = Handle(THREAD, accessing_klass->protection_domain());
|
||||
}
|
||||
Klass* constant_type_klass;
|
||||
if (failure_mode == SignatureStream::ReturnNull) {
|
||||
constant_type_klass = resolve_or_null(signature, class_loader, protection_domain,
|
||||
CHECK_(empty));
|
||||
} else {
|
||||
bool throw_error = (failure_mode == SignatureStream::NCDFError);
|
||||
constant_type_klass = resolve_or_fail(signature, class_loader, protection_domain,
|
||||
throw_error, CHECK_(empty));
|
||||
}
|
||||
if (constant_type_klass == NULL) {
|
||||
return Handle(); // report failure this way
|
||||
}
|
||||
Handle mirror(THREAD, constant_type_klass->java_mirror());
|
||||
if (accessing_klass != NULL) {
|
||||
class_loader = Handle(THREAD, accessing_klass->class_loader());
|
||||
protection_domain = Handle(THREAD, accessing_klass->protection_domain());
|
||||
}
|
||||
ResolvingSignatureStream ss(signature, class_loader, protection_domain, false);
|
||||
oop mirror_oop = ss.as_java_mirror(failure_mode, CHECK_NH);
|
||||
if (mirror_oop == NULL) {
|
||||
return Handle(); // report failure this way
|
||||
}
|
||||
Handle mirror(THREAD, mirror_oop);
|
||||
|
||||
if (accessing_klass != NULL) {
|
||||
// Check accessibility, emulating ConstantPool::verify_constant_pool_resolve.
|
||||
if (accessing_klass != NULL) {
|
||||
Klass* sel_klass = constant_type_klass;
|
||||
Klass* sel_klass = java_lang_Class::as_Klass(mirror());
|
||||
if (sel_klass != NULL) {
|
||||
bool fold_type_to_class = true;
|
||||
LinkResolver::check_klass_accessability(accessing_klass, sel_klass,
|
||||
fold_type_to_class, CHECK_(empty));
|
||||
fold_type_to_class, CHECK_NH);
|
||||
}
|
||||
|
||||
return mirror;
|
||||
|
||||
}
|
||||
|
||||
// Fall through to an error.
|
||||
assert(false, "unsupported mirror syntax");
|
||||
THROW_MSG_(vmSymbols::java_lang_InternalError(), "unsupported mirror syntax", empty);
|
||||
return mirror;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1680,7 +1680,6 @@ void Method::init_intrinsic_id() {
|
||||
}
|
||||
}
|
||||
|
||||
// These two methods are static since a GC may move the Method
|
||||
bool Method::load_signature_classes(const methodHandle& m, TRAPS) {
|
||||
if (!THREAD->can_call_java()) {
|
||||
// There is nothing useful this routine can do from within the Compile thread.
|
||||
@ -1689,16 +1688,11 @@ bool Method::load_signature_classes(const methodHandle& m, TRAPS) {
|
||||
return false;
|
||||
}
|
||||
bool sig_is_loaded = true;
|
||||
Handle class_loader(THREAD, m->method_holder()->class_loader());
|
||||
Handle protection_domain(THREAD, m->method_holder()->protection_domain());
|
||||
ResourceMark rm(THREAD);
|
||||
Symbol* signature = m->signature();
|
||||
for(SignatureStream ss(signature); !ss.is_done(); ss.next()) {
|
||||
for (ResolvingSignatureStream ss(m()); !ss.is_done(); ss.next()) {
|
||||
if (ss.is_reference()) {
|
||||
Symbol* sym = ss.as_symbol();
|
||||
Symbol* name = sym;
|
||||
Klass* klass = SystemDictionary::resolve_or_null(name, class_loader,
|
||||
protection_domain, THREAD);
|
||||
// load everything, including arrays "[Lfoo;"
|
||||
Klass* klass = ss.as_klass(SignatureStream::ReturnNull, THREAD);
|
||||
// We are loading classes eagerly. If a ClassNotFoundException or
|
||||
// a LinkageError was generated, be sure to ignore it.
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
@ -1716,14 +1710,13 @@ bool Method::load_signature_classes(const methodHandle& m, TRAPS) {
|
||||
}
|
||||
|
||||
bool Method::has_unloaded_classes_in_signature(const methodHandle& m, TRAPS) {
|
||||
Handle class_loader(THREAD, m->method_holder()->class_loader());
|
||||
Handle protection_domain(THREAD, m->method_holder()->protection_domain());
|
||||
ResourceMark rm(THREAD);
|
||||
Symbol* signature = m->signature();
|
||||
for(SignatureStream ss(signature); !ss.is_done(); ss.next()) {
|
||||
for(ResolvingSignatureStream ss(m()); !ss.is_done(); ss.next()) {
|
||||
if (ss.type() == T_OBJECT) {
|
||||
Symbol* name = ss.as_symbol();
|
||||
Klass* klass = SystemDictionary::find(name, class_loader, protection_domain, THREAD);
|
||||
// Do not use ss.is_reference() here, since we don't care about
|
||||
// unloaded array component types.
|
||||
Klass* klass = ss.as_klass_if_loaded(THREAD);
|
||||
assert(!HAS_PENDING_EXCEPTION, "as_klass_if_loaded contract");
|
||||
if (klass == NULL) return true;
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,11 @@
|
||||
#include "runtime/thread.inline.hpp"
|
||||
#include "runtime/vframe.inline.hpp"
|
||||
|
||||
static void trace_class_resolution(const Klass* to_class) {
|
||||
static void trace_class_resolution(oop mirror) {
|
||||
if (mirror == NULL || java_lang_Class::is_primitive(mirror)) {
|
||||
return;
|
||||
}
|
||||
Klass* to_class = java_lang_Class::as_Klass(mirror);
|
||||
ResourceMark rm;
|
||||
int line_number = -1;
|
||||
const char * source_file = NULL;
|
||||
@ -750,33 +754,6 @@ void Reflection::check_for_inner_class(const InstanceKlass* outer, const Instanc
|
||||
);
|
||||
}
|
||||
|
||||
// Utility method converting a single SignatureStream element into java.lang.Class instance
|
||||
static oop get_mirror_from_signature(const methodHandle& method,
|
||||
SignatureStream* ss,
|
||||
TRAPS) {
|
||||
|
||||
|
||||
if (is_reference_type(ss->type())) {
|
||||
Symbol* name = ss->as_symbol();
|
||||
oop loader = method->method_holder()->class_loader();
|
||||
oop protection_domain = method->method_holder()->protection_domain();
|
||||
const Klass* k = SystemDictionary::resolve_or_fail(name,
|
||||
Handle(THREAD, loader),
|
||||
Handle(THREAD, protection_domain),
|
||||
true,
|
||||
CHECK_NULL);
|
||||
if (log_is_enabled(Debug, class, resolve)) {
|
||||
trace_class_resolution(k);
|
||||
}
|
||||
return k->java_mirror();
|
||||
}
|
||||
|
||||
assert(ss->type() != T_VOID || ss->at_return_type(),
|
||||
"T_VOID should only appear as return type");
|
||||
|
||||
return java_lang_Class::primitive_mirror(ss->type());
|
||||
}
|
||||
|
||||
static objArrayHandle get_parameter_types(const methodHandle& method,
|
||||
int parameter_count,
|
||||
oop* return_type,
|
||||
@ -787,19 +764,20 @@ static objArrayHandle get_parameter_types(const methodHandle& method,
|
||||
int index = 0;
|
||||
// Collect parameter types
|
||||
ResourceMark rm(THREAD);
|
||||
Symbol* signature = method->signature();
|
||||
SignatureStream ss(signature);
|
||||
while (!ss.at_return_type()) {
|
||||
oop mirror = get_mirror_from_signature(method, &ss, CHECK_(objArrayHandle()));
|
||||
mirrors->obj_at_put(index++, mirror);
|
||||
ss.next();
|
||||
for (ResolvingSignatureStream ss(method()); !ss.is_done(); ss.next()) {
|
||||
oop mirror = ss.as_java_mirror(SignatureStream::NCDFError, CHECK_(objArrayHandle()));
|
||||
if (log_is_enabled(Debug, class, resolve)) {
|
||||
trace_class_resolution(mirror);
|
||||
}
|
||||
if (!ss.at_return_type()) {
|
||||
mirrors->obj_at_put(index++, mirror);
|
||||
} else if (return_type != NULL) {
|
||||
// Collect return type as well
|
||||
assert(ss.at_return_type(), "return type should be present");
|
||||
*return_type = mirror;
|
||||
}
|
||||
}
|
||||
assert(index == parameter_count, "invalid parameter count");
|
||||
if (return_type != NULL) {
|
||||
// Collect return type as well
|
||||
assert(ss.at_return_type(), "return type should be present");
|
||||
*return_type = get_mirror_from_signature(method, &ss, CHECK_(objArrayHandle()));
|
||||
}
|
||||
return mirrors;
|
||||
}
|
||||
|
||||
@ -808,24 +786,11 @@ static objArrayHandle get_exception_types(const methodHandle& method, TRAPS) {
|
||||
}
|
||||
|
||||
static Handle new_type(Symbol* signature, Klass* k, TRAPS) {
|
||||
SignatureStream ss(signature, false);
|
||||
// Basic types
|
||||
BasicType type = ss.is_reference() ? T_OBJECT : ss.type();
|
||||
if (type != T_OBJECT) {
|
||||
return Handle(THREAD, Universe::java_mirror(type));
|
||||
}
|
||||
|
||||
Klass* result =
|
||||
SystemDictionary::resolve_or_fail(signature,
|
||||
Handle(THREAD, k->class_loader()),
|
||||
Handle(THREAD, k->protection_domain()),
|
||||
true, CHECK_(Handle()));
|
||||
|
||||
ResolvingSignatureStream ss(signature, k, false);
|
||||
oop nt = ss.as_java_mirror(SignatureStream::NCDFError, CHECK_NH);
|
||||
if (log_is_enabled(Debug, class, resolve)) {
|
||||
trace_class_resolution(result);
|
||||
trace_class_resolution(nt);
|
||||
}
|
||||
|
||||
oop nt = result->java_mirror();
|
||||
return Handle(THREAD, nt);
|
||||
}
|
||||
|
||||
|
@ -373,7 +373,9 @@ Symbol* SignatureStream::find_symbol() {
|
||||
|
||||
Klass* SignatureStream::as_klass(Handle class_loader, Handle protection_domain,
|
||||
FailureMode failure_mode, TRAPS) {
|
||||
if (!is_reference()) return NULL;
|
||||
if (!is_reference()) {
|
||||
return NULL;
|
||||
}
|
||||
Symbol* name = as_symbol();
|
||||
Klass* k = NULL;
|
||||
if (failure_mode == ReturnNull) {
|
||||
@ -401,10 +403,13 @@ Klass* SignatureStream::as_klass(Handle class_loader, Handle protection_domain,
|
||||
|
||||
oop SignatureStream::as_java_mirror(Handle class_loader, Handle protection_domain,
|
||||
FailureMode failure_mode, TRAPS) {
|
||||
if (!is_reference())
|
||||
if (!is_reference()) {
|
||||
return Universe::java_mirror(type());
|
||||
}
|
||||
Klass* klass = as_klass(class_loader, protection_domain, failure_mode, CHECK_NULL);
|
||||
if (klass == NULL) return NULL;
|
||||
if (klass == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return klass->java_mirror();
|
||||
}
|
||||
|
||||
@ -414,6 +419,52 @@ void SignatureStream::skip_to_return_type() {
|
||||
}
|
||||
}
|
||||
|
||||
ResolvingSignatureStream::ResolvingSignatureStream(Symbol* signature,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
bool is_method)
|
||||
: SignatureStream(signature, is_method),
|
||||
_class_loader(class_loader), _protection_domain(protection_domain)
|
||||
{
|
||||
initialize_load_origin(NULL);
|
||||
}
|
||||
|
||||
ResolvingSignatureStream::ResolvingSignatureStream(Symbol* signature, Klass* load_origin, bool is_method)
|
||||
: SignatureStream(signature, is_method)
|
||||
{
|
||||
assert(load_origin != NULL, "");
|
||||
initialize_load_origin(load_origin);
|
||||
}
|
||||
|
||||
ResolvingSignatureStream::ResolvingSignatureStream(const Method* method)
|
||||
: SignatureStream(method->signature(), true)
|
||||
{
|
||||
initialize_load_origin(method->method_holder());
|
||||
}
|
||||
|
||||
ResolvingSignatureStream::ResolvingSignatureStream(fieldDescriptor& field)
|
||||
: SignatureStream(field.signature(), false)
|
||||
{
|
||||
initialize_load_origin(field.field_holder());
|
||||
}
|
||||
|
||||
void ResolvingSignatureStream::cache_handles(TRAPS) {
|
||||
assert(_load_origin != NULL, "");
|
||||
_class_loader = Handle(THREAD, _load_origin->class_loader());
|
||||
_protection_domain = Handle(THREAD, _load_origin->protection_domain());
|
||||
}
|
||||
|
||||
Klass* ResolvingSignatureStream::as_klass_if_loaded(TRAPS) {
|
||||
Klass* klass = as_klass(CachedOrNull, THREAD);
|
||||
// SD::find does not trigger loading, so there should be no throws
|
||||
// Still, bad things can happen, so we CHECK_NULL and ask callers
|
||||
// to do likewise.
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
}
|
||||
return klass;
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
|
||||
extern bool signature_constants_sane(); // called from basic_types_init()
|
||||
|
@ -564,6 +564,52 @@ class SignatureStream : public StackObj {
|
||||
oop as_java_mirror(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS);
|
||||
};
|
||||
|
||||
// Specialized SignatureStream: used for invoking SystemDictionary to either find
|
||||
// or resolve the underlying type when iterating over a
|
||||
// Java descriptor (or parts of it).
|
||||
class ResolvingSignatureStream : public SignatureStream {
|
||||
Klass* _load_origin;
|
||||
bool _handles_cached;
|
||||
Handle _class_loader; // cached when needed
|
||||
Handle _protection_domain; // cached when needed
|
||||
|
||||
void initialize_load_origin(Klass* load_origin) {
|
||||
_load_origin = load_origin;
|
||||
_handles_cached = (load_origin == NULL);
|
||||
}
|
||||
void need_handles(TRAPS) {
|
||||
if (!_handles_cached) {
|
||||
cache_handles(THREAD);
|
||||
_handles_cached = true;
|
||||
}
|
||||
}
|
||||
void cache_handles(TRAPS);
|
||||
|
||||
public:
|
||||
ResolvingSignatureStream(Symbol* signature, Klass* load_origin, bool is_method = true);
|
||||
ResolvingSignatureStream(Symbol* signature, Handle class_loader, Handle protection_domain, bool is_method = true);
|
||||
ResolvingSignatureStream(const Method* method);
|
||||
ResolvingSignatureStream(fieldDescriptor& field);
|
||||
|
||||
Klass* load_origin() { return _load_origin; }
|
||||
Handle class_loader(TRAPS) { need_handles(THREAD); return _class_loader; }
|
||||
Handle protection_domain(TRAPS) { need_handles(THREAD); return _protection_domain; }
|
||||
|
||||
Klass* as_klass_if_loaded(TRAPS);
|
||||
Klass* as_klass(FailureMode failure_mode, TRAPS) {
|
||||
need_handles(THREAD);
|
||||
return SignatureStream::as_klass(_class_loader, _protection_domain,
|
||||
failure_mode, THREAD);
|
||||
}
|
||||
oop as_java_mirror(FailureMode failure_mode, TRAPS) {
|
||||
if (is_reference()) {
|
||||
need_handles(THREAD);
|
||||
}
|
||||
return SignatureStream::as_java_mirror(_class_loader, _protection_domain,
|
||||
failure_mode, THREAD);
|
||||
}
|
||||
};
|
||||
|
||||
// Here is how all the SignatureIterator classes invoke the
|
||||
// SignatureStream engine to do their parsing.
|
||||
template<typename T> inline
|
||||
|
Loading…
Reference in New Issue
Block a user