mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8238358: Implementation of JEP 371: Hidden Classes
Co-authored-by: Lois Foltan <lois.foltan@oracle.com> Co-authored-by: David Holmes <david.holmes@oracle.com> Co-authored-by: Harold Seigel <harold.seigel@oracle.com> Co-authored-by: Serguei Spitsyn <serguei.spitsyn@oracle.com> Co-authored-by: Alex Buckley <alex.buckley@oracle.com> Co-authored-by: Jamsheed Mohammed C M <jamsheed.c.m@oracle.com> Co-authored-by: Jan Lahoda <jan.lahoda@oracle.com> Co-authored-by: Amy Lu <amy.lu@oracle.com> Reviewed-by: alanb, cjplummer, coleenp, dholmes, dlong, forax, jlahoda, psandoz, plevart, sspitsyn, vromero
This commit is contained in:
parent
642041adbc
commit
7cc1371059
198 changed files with 9526 additions and 1575 deletions
|
@ -111,6 +111,46 @@ oop SystemDictionary::_java_platform_loader = NULL;
|
|||
|
||||
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
|
||||
|
||||
|
@ -822,7 +862,7 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
|||
// class loaders holding the ObjectLock shouldn't find the class here
|
||||
InstanceKlass* check = find_class(d_hash, name, dictionary);
|
||||
if (check != NULL) {
|
||||
// Klass is already loaded, so return it after checking/adding protection domain
|
||||
// Klass is already loaded, so return it after checking/adding protection domain
|
||||
k = check;
|
||||
class_has_been_loaded = true;
|
||||
}
|
||||
|
@ -982,24 +1022,36 @@ Klass* SystemDictionary::find_instance_or_array_klass(Symbol* class_name,
|
|||
|
||||
// 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
|
||||
// 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,
|
||||
Handle protection_domain,
|
||||
ClassFileStream* st,
|
||||
const InstanceKlass* unsafe_anonymous_host,
|
||||
GrowableArray<Handle>* cp_patches,
|
||||
const ClassLoadInfo& cl_info,
|
||||
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);
|
||||
|
||||
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());
|
||||
}
|
||||
|
@ -1015,15 +1067,16 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
|
|||
InstanceKlass* k = KlassFactory::create_from_stream(st,
|
||||
class_name,
|
||||
loader_data,
|
||||
protection_domain,
|
||||
unsafe_anonymous_host,
|
||||
cp_patches,
|
||||
cl_info,
|
||||
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()));
|
||||
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);
|
||||
|
@ -1036,12 +1089,14 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
|
|||
|
||||
// Rewrite and patch constant pool here.
|
||||
k->link_class(CHECK_NULL);
|
||||
if (cp_patches != NULL) {
|
||||
k->constants()->patch_resolved_references(cp_patches);
|
||||
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.
|
||||
k->eager_initialize(CHECK_NULL);
|
||||
if (is_unsafe_anon_class) {
|
||||
k->eager_initialize(CHECK_NULL);
|
||||
}
|
||||
|
||||
// notify jvmti
|
||||
if (JvmtiExport::should_post_class_load()) {
|
||||
|
@ -1052,7 +1107,7 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
|
|||
post_class_load_event(&class_load_start_event, k, loader_data);
|
||||
}
|
||||
}
|
||||
assert(unsafe_anonymous_host != NULL || NULL == cp_patches,
|
||||
assert(is_unsafe_anon_class || NULL == cl_info.cp_patches(),
|
||||
"cp_patches only found with unsafe_anonymous_host");
|
||||
|
||||
return k;
|
||||
|
@ -1107,13 +1162,8 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name,
|
|||
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);
|
||||
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");
|
||||
|
@ -2327,6 +2377,42 @@ Symbol* SystemDictionary::find_resolution_error(const constantPoolHandle& pool,
|
|||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue