< 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 >