< prev index next >
src/hotspot/share/classfile/systemDictionary.cpp
Print this page
rev 58565 : 8238358: Implementation of JEP 371: Hidden Classes
Reviewed-by: duke
Contributed-by: mandy.chung@oracle.com, lois.foltan@oracle.com, david.holmes@oracle.com, harold.seigel@oracle.com, serguei.spitsyn@oracle.com, alex.buckley@oracle.com, jamsheed.c.m@oracle.com
*** 109,118 ****
--- 109,158 ----
// Default ProtectionDomainCacheSize value
const int defaultProtectionDomainCacheSize = 1009;
+ ClassLoadInfo::ClassLoadInfo() {
+ _protection_domain = Handle();
+ _unsafe_anonymous_host = NULL;
+ _cp_patches = NULL;
+ _class_hidden_info._dynamic_nest_host = NULL;
+ _class_hidden_info._class_data = Handle();
+ _is_hidden = false;
+ _is_strong_hidden = false;
+ _can_access_vm_annotations = false;
+ }
+
+ ClassLoadInfo::ClassLoadInfo(Handle protection_domain) {
+ _protection_domain = protection_domain;
+ _unsafe_anonymous_host = NULL;
+ _cp_patches = NULL;
+ _class_hidden_info._dynamic_nest_host = NULL;
+ _class_hidden_info._class_data = Handle();
+ _is_hidden = false;
+ _is_strong_hidden = false;
+ _can_access_vm_annotations = false;
+ }
+
+ ClassLoadInfo::ClassLoadInfo(Handle protection_domain,
+ const InstanceKlass* unsafe_anonymous_host,
+ GrowableArray<Handle>* cp_patches,
+ InstanceKlass* dynamic_nest_host,
+ Handle class_data,
+ bool is_hidden,
+ bool is_strong_hidden,
+ bool can_access_vm_annotations) {
+ _protection_domain = protection_domain;
+ _unsafe_anonymous_host = unsafe_anonymous_host;
+ _cp_patches = cp_patches;
+ _class_hidden_info._dynamic_nest_host = dynamic_nest_host;
+ _class_hidden_info._class_data = class_data;
+ _is_hidden = is_hidden;
+ _is_strong_hidden = is_strong_hidden;
+ _can_access_vm_annotations = can_access_vm_annotations;
+ }
+
// ----------------------------------------------------------------------------
// Java-level SystemLoader and PlatformLoader
oop SystemDictionary::java_system_loader() {
return _java_system_loader;
*** 980,1007 ****
return k;
}
// Note: this method is much like resolve_from_stream, but
// does not publish the classes via the SystemDictionary.
! // Handles unsafe_DefineAnonymousClass and redefineclasses
! // RedefinedClasses do not add to the class hierarchy
InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
Handle class_loader,
- Handle protection_domain,
ClassFileStream* st,
! const InstanceKlass* unsafe_anonymous_host,
! GrowableArray<Handle>* cp_patches,
TRAPS) {
EventClassLoad class_load_start_event;
ClassLoaderData* loader_data;
! if (unsafe_anonymous_host != NULL) {
! // Create a new CLD for an unsafe anonymous class, that uses the same class loader
! // as the unsafe_anonymous_host
! guarantee(unsafe_anonymous_host->class_loader() == class_loader(), "should be the same");
! loader_data = ClassLoaderData::unsafe_anonymous_class_loader_data(class_loader);
} else {
loader_data = ClassLoaderData::class_loader_data(class_loader());
}
assert(st != NULL, "invariant");
--- 1020,1059 ----
return k;
}
// Note: this method is much like resolve_from_stream, but
// does not publish the classes via the SystemDictionary.
! // Handles Lookup.defineClass hidden, unsafe_DefineAnonymousClass
! // and redefineclasses. RedefinedClasses do not add to the class hierarchy.
InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
Handle class_loader,
ClassFileStream* st,
! const ClassLoadInfo& cl_info,
TRAPS) {
EventClassLoad class_load_start_event;
ClassLoaderData* loader_data;
!
! bool is_unsafe_anon_class = cl_info.unsafe_anonymous_host() != NULL;
!
! if (is_unsafe_anon_class) {
! // - for unsafe anonymous class: create a new CLD whith a class holder that uses
! // the same class loader as the unsafe_anonymous_host.
! guarantee(cl_info.unsafe_anonymous_host()->class_loader() == class_loader(),
! "should be the same");
! loader_data = ClassLoaderData::has_class_mirror_holder_cld(class_loader);
! } else if (cl_info.is_hidden()) {
! // - for hidden classes that are not strong: create a new CLD that has a class holder and
! // whose loader is the Lookup class' loader.
! // - for hidden class: add the class to the Lookup class' loader's CLD.
! if (!cl_info.is_strong_hidden()) {
! loader_data = ClassLoaderData::has_class_mirror_holder_cld(class_loader);
! } else {
! // This hidden class goes into the regular CLD pool for this loader.
! loader_data = register_loader(class_loader);
! }
} else {
loader_data = ClassLoaderData::class_loader_data(class_loader());
}
assert(st != NULL, "invariant");
*** 1013,1031 ****
// throw potential ClassFormatErrors.
InstanceKlass* k = KlassFactory::create_from_stream(st,
class_name,
loader_data,
! protection_domain,
! unsafe_anonymous_host,
! cp_patches,
CHECK_NULL);
! if (unsafe_anonymous_host != NULL && k != NULL) {
! // Unsafe anonymous classes must update ClassLoaderData holder (was unsafe_anonymous_host loader)
! // so that they can be unloaded when the mirror is no longer referenced.
k->class_loader_data()->initialize_holder(Handle(THREAD, k->java_mirror()));
{
MutexLocker mu_r(THREAD, Compile_lock);
// Add to class hierarchy, initialize vtables, and do possible
--- 1065,1084 ----
// throw potential ClassFormatErrors.
InstanceKlass* k = KlassFactory::create_from_stream(st,
class_name,
loader_data,
! cl_info,
CHECK_NULL);
! if ((cl_info.is_hidden() || is_unsafe_anon_class) && k != NULL) {
! // Hidden classes that are not strong and unsafe anonymous classes must update
! // ClassLoaderData holder so that they can be unloaded when the mirror is no
! // longer referenced.
! if (!cl_info.is_strong_hidden() || is_unsafe_anon_class) {
k->class_loader_data()->initialize_holder(Handle(THREAD, k->java_mirror()));
+ }
{
MutexLocker mu_r(THREAD, Compile_lock);
// Add to class hierarchy, initialize vtables, and do possible
*** 1034,1060 ****
// But, do not add to dictionary.
}
// Rewrite and patch constant pool here.
k->link_class(CHECK_NULL);
! if (cp_patches != NULL) {
! k->constants()->patch_resolved_references(cp_patches);
}
// If it's anonymous, initialize it now, since nobody else will.
k->eager_initialize(CHECK_NULL);
// notify jvmti
if (JvmtiExport::should_post_class_load()) {
assert(THREAD->is_Java_thread(), "thread->is_Java_thread()");
JvmtiExport::post_class_load((JavaThread *) THREAD, k);
}
if (class_load_start_event.should_commit()) {
post_class_load_event(&class_load_start_event, k, loader_data);
}
}
! assert(unsafe_anonymous_host != NULL || NULL == cp_patches,
"cp_patches only found with unsafe_anonymous_host");
return k;
}
--- 1087,1115 ----
// But, do not add to dictionary.
}
// Rewrite and patch constant pool here.
k->link_class(CHECK_NULL);
! if (cl_info.cp_patches() != NULL) {
! k->constants()->patch_resolved_references(cl_info.cp_patches());
}
// If it's anonymous, initialize it now, since nobody else will.
+ if (is_unsafe_anon_class) {
k->eager_initialize(CHECK_NULL);
+ }
// notify jvmti
if (JvmtiExport::should_post_class_load()) {
assert(THREAD->is_Java_thread(), "thread->is_Java_thread()");
JvmtiExport::post_class_load((JavaThread *) THREAD, k);
}
if (class_load_start_event.should_commit()) {
post_class_load_event(&class_load_start_event, k, loader_data);
}
}
! assert(is_unsafe_anon_class || NULL == cl_info.cp_patches(),
"cp_patches only found with unsafe_anonymous_host");
return k;
}
*** 1105,1121 ****
if (k == NULL) {
if (st->buffer() == NULL) {
return NULL;
}
! k = KlassFactory::create_from_stream(st,
! class_name,
! loader_data,
! protection_domain,
! NULL, // unsafe_anonymous_host
! NULL, // cp_patches
! CHECK_NULL);
}
assert(k != NULL, "no klass created");
Symbol* h_name = k->name();
assert(class_name == NULL || class_name == h_name, "name mismatch");
--- 1160,1171 ----
if (k == NULL) {
if (st->buffer() == NULL) {
return NULL;
}
! ClassLoadInfo cl_info(protection_domain);
! k = KlassFactory::create_from_stream(st, class_name, loader_data, cl_info, CHECK_NULL);
}
assert(k != NULL, "no klass created");
Symbol* h_name = k->name();
assert(class_name == NULL || class_name == h_name, "name mismatch");
*** 2323,2332 ****
--- 2373,2418 ----
return NULL;
}
}
}
+ // Add an entry to resolution error table to record an error in resolving or
+ // validating a nest host. This is used to construct informative error
+ // messages when IllegalAccessError's occur. If an entry already exists it will
+ // be updated with the nest host error message.
+ void SystemDictionary::add_nest_host_error(const constantPoolHandle& pool,
+ int which,
+ const char* message) {
+ unsigned int hash = resolution_errors()->compute_hash(pool, which);
+ int index = resolution_errors()->hash_to_index(hash);
+ {
+ MutexLocker ml(Thread::current(), SystemDictionary_lock);
+ ResolutionErrorEntry* entry = resolution_errors()->find_entry(index, hash, pool, which);
+ if (entry != NULL) {
+ assert(entry->nest_host_error() == NULL, "Nest host error message already set!");
+ entry->set_nest_host_error(message);
+ } else {
+ resolution_errors()->add_entry(index, hash, pool, which, message);
+ }
+ }
+ }
+
+ // Lookup any nest host error
+ const char* SystemDictionary::find_nest_host_error(const constantPoolHandle& pool, int which) {
+ unsigned int hash = resolution_errors()->compute_hash(pool, which);
+ int index = resolution_errors()->hash_to_index(hash);
+ {
+ MutexLocker ml(Thread::current(), SystemDictionary_lock);
+ ResolutionErrorEntry* entry = resolution_errors()->find_entry(index, hash, pool, which);
+ if (entry != NULL) {
+ return entry->nest_host_error();
+ } else {
+ return NULL;
+ }
+ }
+ }
+
// Signature constraints ensure that callers and callees agree about
// the meaning of type names in their signatures. This routine is the
// intake for constraints. It collects them from several places:
//
< prev index next >