--- old/make/hotspot/symbols/symbols-unix 2019-12-03 19:36:27.000000000 -0800 +++ new/make/hotspot/symbols/symbols-unix 2019-12-03 19:36:27.000000000 -0800 @@ -141,6 +141,7 @@ JVM_InvokeMethod JVM_IsArrayClass JVM_IsConstructorIx +JVM_IsHiddenClass JVM_IsInterface JVM_IsPrimitiveClass JVM_IsSameClassPackage @@ -149,6 +150,7 @@ JVM_IsVMGeneratedMethodIx JVM_LatestUserDefinedLoader JVM_LoadLibrary +JVM_LookupDefineClass JVM_MaxMemory JVM_MaxObjectInspectionAge JVM_MonitorNotify --- old/src/hotspot/share/aot/aotCodeHeap.cpp 2019-12-03 19:36:28.000000000 -0800 +++ new/src/hotspot/share/aot/aotCodeHeap.cpp 2019-12-03 19:36:28.000000000 -0800 @@ -1049,7 +1049,7 @@ InstanceKlass* dyno = InstanceKlass::cast(dyno_klass); - if (!dyno->is_unsafe_anonymous()) { + if (!dyno->is_hidden() && !dyno->is_unsafe_anonymous()) { if (_klasses_got[dyno_data->_got_index] != dyno) { // compile-time class different from runtime class, fail and deoptimize sweep_dependent_methods(holder_data); --- old/src/hotspot/share/aot/aotLoader.cpp 2019-12-03 19:36:29.000000000 -0800 +++ new/src/hotspot/share/aot/aotLoader.cpp 2019-12-03 19:36:29.000000000 -0800 @@ -43,7 +43,7 @@ #define FOR_ALL_AOT_LIBRARIES(lib) for (GrowableArrayIterator lib = libraries()->begin(); lib != libraries()->end(); ++lib) void AOTLoader::load_for_klass(InstanceKlass* ik, Thread* thread) { - if (ik->is_unsafe_anonymous()) { + if (ik->is_hidden() || ik->is_unsafe_anonymous()) { // don't even bother return; } @@ -58,7 +58,7 @@ uint64_t AOTLoader::get_saved_fingerprint(InstanceKlass* ik) { assert(UseAOT, "called only when AOT is enabled"); - if (ik->is_unsafe_anonymous()) { + if (ik->is_hidden() || ik->is_unsafe_anonymous()) { // don't even bother return 0; } --- old/src/hotspot/share/ci/ciField.cpp 2019-12-03 19:36:30.000000000 -0800 +++ new/src/hotspot/share/ci/ciField.cpp 2019-12-03 19:36:30.000000000 -0800 @@ -221,9 +221,10 @@ // Even if general trusting is disabled, trust system-built closures in these packages. if (holder->is_in_package("java/lang/invoke") || holder->is_in_package("sun/invoke")) return true; - // Trust VM unsafe anonymous classes. They are private API (jdk.internal.misc.Unsafe) - // and can't be serialized, so there is no hacking of finals going on with them. - if (holder->is_unsafe_anonymous()) + // Trust VM hidden and unsafe anonymous classes. They are created via Lookup.defineClass or + // the private API (jdk.internal.misc.Unsafe) and can't be serialized, so there is no hacking + // of finals going on with them. + if (holder->is_hidden() || holder->is_unsafe_anonymous()) return true; // Trust final fields in all boxed classes if (holder->is_box_klass()) --- old/src/hotspot/share/ci/ciInstanceKlass.cpp 2019-12-03 19:36:31.000000000 -0800 +++ new/src/hotspot/share/ci/ciInstanceKlass.cpp 2019-12-03 19:36:31.000000000 -0800 @@ -63,6 +63,7 @@ _has_nonstatic_fields = ik->has_nonstatic_fields(); _has_nonstatic_concrete_methods = ik->has_nonstatic_concrete_methods(); _is_unsafe_anonymous = ik->is_unsafe_anonymous(); + _is_hidden = ik->is_hidden(); _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields: _has_injected_fields = -1; _implementor = NULL; // we will fill these lazily @@ -73,13 +74,13 @@ // InstanceKlass are created for both weak and strong metadata. Ensuring this metadata // alive covers the cases where there are weak roots without performance cost. oop holder = ik->klass_holder(); - if (ik->is_unsafe_anonymous()) { + if (ik->class_loader_data()->is_shortlived()) { // Though ciInstanceKlass records class loader oop, it's not enough to keep - // VM unsafe anonymous classes alive (loader == NULL). Klass holder should + // VM weak hidden and unsafe anonymous classes alive (loader == NULL). Klass holder should // be used instead. It is enough to record a ciObject, since cached elements are never removed // during ciObjectFactory lifetime. ciObjectFactory itself is created for // every compilation and lives for the whole duration of the compilation. - assert(holder != NULL, "holder of unsafe anonymous class is the mirror which is never null"); + assert(holder != NULL, "holder of hidden or unsafe anonymous class is the mirror which is never null"); (void)CURRENT_ENV->get_object(holder); } @@ -123,6 +124,7 @@ _nonstatic_fields = NULL; _has_injected_fields = -1; _is_unsafe_anonymous = false; + _is_hidden = false; _loader = loader; _protection_domain = protection_domain; _is_shared = false; --- old/src/hotspot/share/ci/ciInstanceKlass.hpp 2019-12-03 19:36:32.000000000 -0800 +++ new/src/hotspot/share/ci/ciInstanceKlass.hpp 2019-12-03 19:36:31.000000000 -0800 @@ -56,6 +56,7 @@ bool _has_nonstatic_fields; bool _has_nonstatic_concrete_methods; bool _is_unsafe_anonymous; + bool _is_hidden; ciFlags _flags; jint _nonstatic_field_size; @@ -195,6 +196,10 @@ return _is_unsafe_anonymous; } + bool is_hidden() { + return _is_hidden; + } + ciInstanceKlass* get_canonical_holder(int offset); ciField* get_field_by_offset(int field_offset, bool is_static); ciField* get_field_by_name(ciSymbol* name, ciSymbol* signature, bool is_static); --- old/src/hotspot/share/classfile/classFileParser.cpp 2019-12-03 19:36:33.000000000 -0800 +++ new/src/hotspot/share/classfile/classFileParser.cpp 2019-12-03 19:36:32.000000000 -0800 @@ -1090,7 +1090,7 @@ assert((int)_annotation_LIMIT <= (int)sizeof(_annotations_present) * BitsPerByte, ""); } // If this annotation name has an ID, report it (or _none). - ID annotation_index(const ClassLoaderData* loader_data, const Symbol* name); + ID annotation_index(const ClassLoaderData* loader_data, const Symbol* name, const bool can_access_vm_annotations); // Set the annotation name: void set_annotation(ID id) { assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob"); @@ -1223,6 +1223,7 @@ const u1* buffer, int limit, AnnotationCollector* coll, ClassLoaderData* loader_data, + const bool can_access_vm_annotations, TRAPS) { assert(cp != NULL, "invariant"); @@ -1268,7 +1269,7 @@ } // Here is where parsing particular annotations will take place. - AnnotationCollector::ID id = coll->annotation_index(loader_data, aname); + AnnotationCollector::ID id = coll->annotation_index(loader_data, aname, can_access_vm_annotations); if (AnnotationCollector::_unknown == id) continue; coll->set_annotation(id); @@ -1394,6 +1395,7 @@ runtime_visible_annotations_length, parsed_annotations, _loader_data, + _can_access_vm_annotations, CHECK); cfs->skip_u1_fast(runtime_visible_annotations_length); } else if (attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { @@ -2053,12 +2055,14 @@ AnnotationCollector::ID AnnotationCollector::annotation_index(const ClassLoaderData* loader_data, - const Symbol* name) { + const Symbol* name, + const bool can_access_vm_annotations) { const vmSymbols::SID sid = vmSymbols::find_sid(name); // Privileged code can use all annotations. Other code silently drops some. const bool privileged = loader_data->is_the_null_class_loader_data() || loader_data->is_platform_class_loader_data() || - loader_data->is_unsafe_anonymous(); + loader_data->is_shortlived() || + can_access_vm_annotations; switch (sid) { case vmSymbols::VM_SYMBOL_ENUM_NAME(reflect_CallerSensitive_signature): { if (_location != _in_method) break; // only allow for methods @@ -2665,6 +2669,7 @@ runtime_visible_annotations_length, &parsed_annotations, _loader_data, + _can_access_vm_annotations, CHECK_NULL); cfs->skip_u1_fast(runtime_visible_annotations_length); } else if (method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { @@ -3427,6 +3432,7 @@ runtime_visible_annotations_length, parsed_annotations, _loader_data, + _can_access_vm_annotations, CHECK); cfs->skip_u1_fast(runtime_visible_annotations_length); } else if (tag == vmSymbols::tag_runtime_invisible_annotations()) { @@ -5417,7 +5423,9 @@ } } -InstanceKlass* ClassFileParser::create_instance_klass(bool changed_by_loadhook, TRAPS) { +InstanceKlass* ClassFileParser::create_instance_klass(bool changed_by_loadhook, + const ClassInstanceInfo& cl_inst_info, + TRAPS) { if (_klass != NULL) { return _klass; } @@ -5425,7 +5433,7 @@ InstanceKlass* const ik = InstanceKlass::allocate_instance_klass(*this, CHECK_NULL); - fill_instance_klass(ik, changed_by_loadhook, CHECK_NULL); + fill_instance_klass(ik, changed_by_loadhook, cl_inst_info, CHECK_NULL); assert(_klass == ik, "invariant"); @@ -5451,7 +5459,10 @@ return ik; } -void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loadhook, TRAPS) { +void ClassFileParser::fill_instance_klass(InstanceKlass* ik, + bool changed_by_loadhook, + const ClassInstanceInfo& cl_inst_info, + TRAPS) { assert(ik != NULL, "invariant"); // Set name and CLD before adding to CLD @@ -5487,6 +5498,11 @@ // the parser onto the InstanceKlass* apply_parsed_class_metadata(ik, _java_fields_count, CHECK); + // can only set dynamic nest-host after static nest information is set + if (cl_inst_info.dynamic_nest_host() != NULL) { + ik->set_nest_host(cl_inst_info.dynamic_nest_host(), CHECK); + } + // note that is not safe to use the fields in the parser from this point on assert(NULL == _cp, "invariant"); assert(NULL == _fields, "invariant"); @@ -5510,11 +5526,11 @@ ik->set_this_class_index(_this_class_index); - if (is_unsafe_anonymous()) { + if (_is_hidden || is_unsafe_anonymous()) { // _this_class_index is a CONSTANT_Class entry that refers to this - // anonymous class itself. If this class needs to refer to its own methods or - // fields, it would use a CONSTANT_MethodRef, etc, which would reference - // _this_class_index. However, because this class is anonymous (it's + // hidden or anonymous class itself. If this class needs to refer to its own + // methods or fields, it would use a CONSTANT_MethodRef, etc, which would reference + // _this_class_index. However, because this class is hidden or anonymous (it's // not stored in SystemDictionary), _this_class_index cannot be resolved // with ConstantPool::klass_at_impl, which does a SystemDictionary lookup. // Therefore, we must eagerly resolve _this_class_index now. @@ -5530,12 +5546,19 @@ assert (ik->is_unsafe_anonymous(), "should be the same"); ik->set_unsafe_anonymous_host(_unsafe_anonymous_host); } + if (_is_hidden) { + ik->set_is_hidden(); + } // Set PackageEntry for this_klass oop cl = ik->class_loader(); Handle clh = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(cl)); ClassLoaderData* cld = ClassLoaderData::class_loader_data_or_null(clh()); ik->set_package(cld, CHECK); + // Obtain this_klass' module entry + ModuleEntry* module_entry = ik->module(); + assert(module_entry != NULL, "module_entry should always be set"); + const Array* const methods = ik->methods(); assert(methods != NULL, "invariant"); @@ -5591,10 +5614,6 @@ check_illegal_static_method(ik, CHECK); } - // Obtain this_klass' module entry - ModuleEntry* module_entry = ik->module(); - assert(module_entry != NULL, "module_entry should always be set"); - // Obtain java.lang.Module Handle module_handle(THREAD, module_entry->module()); @@ -5604,6 +5623,7 @@ Handle(THREAD, _loader_data->class_loader()), module_handle, _protection_domain, + cl_inst_info.class_data(), CHECK); assert(_all_mirandas != NULL, "invariant"); @@ -5677,18 +5697,6 @@ debug_only(ik->verify();) } -void ClassFileParser::update_class_name(Symbol* new_class_name) { - // Decrement the refcount in the old name, since we're clobbering it. - _class_name->decrement_refcount(); - - _class_name = new_class_name; - // Increment the refcount of the new name. - // Now the ClassFileParser owns this name and will decrement in - // the destructor. - _class_name->increment_refcount(); -} - - // For an unsafe anonymous class that is in the unnamed package, move it to its host class's // package by prepending its host class's package name to its class name and setting // its _class_name field. @@ -5757,14 +5765,17 @@ Handle protection_domain, const InstanceKlass* unsafe_anonymous_host, GrowableArray* cp_patches, + const bool is_hidden, + const bool can_access_vm_annotations, Publicity pub_level, TRAPS) : _stream(stream), - _requested_name(name), _class_name(NULL), _loader_data(loader_data), _unsafe_anonymous_host(unsafe_anonymous_host), _cp_patches(cp_patches), + _is_hidden(is_hidden), + _can_access_vm_annotations(can_access_vm_annotations), _num_patched_klasses(0), _max_num_patched_klasses(0), _orig_cp_size(0), @@ -5991,10 +6002,15 @@ cp_size, CHECK); _orig_cp_size = cp_size; - if (int(cp_size) + _max_num_patched_klasses > 0xffff) { - THROW_MSG(vmSymbols::java_lang_InternalError(), "not enough space for patched classes"); + if (is_hidden()) { // Add a slot for hidden class name. + assert(_max_num_patched_klasses == 0, "Sanity check"); + cp_size++; + } else { + if (int(cp_size) + _max_num_patched_klasses > 0xffff) { + THROW_MSG(vmSymbols::java_lang_InternalError(), "not enough space for patched classes"); + } + cp_size += _max_num_patched_klasses; } - cp_size += _max_num_patched_klasses; _cp = ConstantPool::allocate(_loader_data, cp_size, @@ -6045,36 +6061,100 @@ Symbol* const class_name_in_cp = cp->klass_name_at(_this_class_index); assert(class_name_in_cp != NULL, "class_name can't be null"); - // Update _class_name to reflect the name in the constant pool - update_class_name(class_name_in_cp); - // Don't need to check whether this class name is legal or not. // It has been checked when constant pool is parsed. // However, make sure it is not an array type. if (_need_verify) { - guarantee_property(_class_name->char_at(0) != JVM_SIGNATURE_ARRAY, + guarantee_property(class_name_in_cp->char_at(0) != JVM_SIGNATURE_ARRAY, "Bad class name in class file %s", CHECK); } - // Checks if name in class file matches requested name - if (_requested_name != NULL && _requested_name != _class_name) { - ResourceMark rm(THREAD); - Exceptions::fthrow( - THREAD_AND_LOCATION, - vmSymbols::java_lang_NoClassDefFoundError(), - "%s (wrong name: %s)", - _class_name->as_C_string(), - _requested_name != NULL ? _requested_name->as_C_string() : "NoName" - ); - return; +#ifdef ASSERT + // Basic sanity checks + assert(!(_is_hidden && (_unsafe_anonymous_host != NULL)), "mutually exclusive variants"); + + if (_unsafe_anonymous_host != NULL) { + assert(_class_name == vmSymbols::unknown_class_name(), "A named anonymous class???"); } + if (_is_hidden) { + assert(_class_name != vmSymbols::unknown_class_name(), "hidden classes should have a special name"); + } +#endif + + // Update the _class_name as needed depending on whether this is a named, + // un-named, hidden or unsafe-anonymous class. + + if (_is_hidden) { + ResourceMark rm(THREAD); + assert(_class_name != NULL, "Unexpected null _class_name"); +#ifdef ASSERT + if (_need_verify) { + verify_legal_class_name(_class_name, CHECK); + } +#endif - // if this is an anonymous class fix up its name if it's in the unnamed + // Construct hidden name from _class_name, "+", and &_cp. Note that we can't + // use a '/' because that confuses finding the class's package. Also, can't + // use an illegal char such as ';' because that causes serialization issues + // and issues with hidden classes that create their own hidden classes. + char addr_buf[20]; + jio_snprintf(addr_buf, 20, INTPTR_FORMAT, p2i(_cp)); + size_t new_name_len = _class_name->utf8_length() + 2 + strlen(addr_buf); + char* new_name = NEW_RESOURCE_ARRAY(char, new_name_len); + jio_snprintf(new_name, new_name_len, "%s+%s", + _class_name->as_C_string(), addr_buf); + _class_name->decrement_refcount(); + _class_name = SymbolTable::new_symbol(new_name); + _class_name->increment_refcount(); + + // Add a Utf8 entry containing the hidden name. + assert(_class_name != NULL, "Unexpected null _class_name"); + int hidden_index = _orig_cp_size; // this is an extra slot we added + cp->symbol_at_put(hidden_index, _class_name); + + // Update this_class_index's slot in the constant pool with the new Utf8 entry. + // We have to update the resolved_klass_index and the name_index together + // so extract the existing resolved_klass_index first. + CPKlassSlot cp_klass_slot = cp->klass_slot_at(_this_class_index); + int resolved_klass_index = cp_klass_slot.resolved_klass_index(); + cp->unresolved_klass_at_put(_this_class_index, hidden_index, resolved_klass_index); + assert(cp->klass_slot_at(_this_class_index).name_index() == _orig_cp_size, + "Bad name_index"); + + // NOTE: !_is_hidden does not imply "findable" as it could be an old-style + // "hidden" unsafe-anonymous class + + // If this is an anonymous class fix up its name if it is in the unnamed // package. Otherwise, throw IAE if it is in a different package than // its host class. - if (_unsafe_anonymous_host != NULL) { + } else if (_unsafe_anonymous_host != NULL) { + Symbol* old_class_name = _class_name; + _class_name = class_name_in_cp; + _class_name->increment_refcount(); fix_unsafe_anonymous_class_name(CHECK); + old_class_name->decrement_refcount(); + + } else { + // Check if name in class file matches given name + if (_class_name != class_name_in_cp) { + if (_class_name != vmSymbols::unknown_class_name()) { + ResourceMark rm(THREAD); + Exceptions::fthrow(THREAD_AND_LOCATION, + vmSymbols::java_lang_NoClassDefFoundError(), + "%s (wrong name: %s)", + class_name_in_cp->as_C_string(), + _class_name->as_C_string() + ); + return; + } else { + // The class name was not known by the caller so we set it from + // the value in the CP. + _class_name = class_name_in_cp; + _class_name->increment_refcount(); + } + // else nothing to do: the expected class name matches what is in the CP + } } // Verification prevents us from creating names with dots in them, this @@ -6099,9 +6179,10 @@ warning("DumpLoadedClassList and CDS are not supported in exploded build"); DumpLoadedClassList = NULL; } else if (SystemDictionaryShared::is_sharing_possible(_loader_data) && + !_is_hidden && _unsafe_anonymous_host == NULL) { // Only dump the classes that can be stored into CDS archive. - // Unsafe anonymous classes such as generated LambdaForm classes are also not included. + // Hidden and unsafe anonymous classes such as generated LambdaForm classes are also not included. oop class_loader = _loader_data->class_loader(); ResourceMark rm(THREAD); bool skip = false; --- old/src/hotspot/share/classfile/classFileParser.hpp 2019-12-03 19:36:34.000000000 -0800 +++ new/src/hotspot/share/classfile/classFileParser.hpp 2019-12-03 19:36:33.000000000 -0800 @@ -36,6 +36,7 @@ class Array; class ClassFileStream; class ClassLoaderData; +class ClassInstanceInfo; class CompressedLineNumberWriteStream; class ConstMethod; class FieldInfo; @@ -78,11 +79,12 @@ typedef void unsafe_u2; const ClassFileStream* _stream; // Actual input stream - const Symbol* _requested_name; Symbol* _class_name; mutable ClassLoaderData* _loader_data; const InstanceKlass* _unsafe_anonymous_host; GrowableArray* _cp_patches; // overrides for CP entries + const bool _is_hidden; + const bool _can_access_vm_annotations; int _num_patched_klasses; int _max_num_patched_klasses; int _orig_cp_size; @@ -175,7 +177,9 @@ void prepend_host_package_name(const InstanceKlass* unsafe_anonymous_host, TRAPS); void fix_unsafe_anonymous_class_name(TRAPS); - void fill_instance_klass(InstanceKlass* ik, bool cf_changed_in_CFLH, TRAPS); + void fill_instance_klass(InstanceKlass* ik, bool cf_changed_in_CFLH, + const ClassInstanceInfo& cl_inst_info, TRAPS); + void set_klass(InstanceKlass* instance); void set_class_bad_constant_seen(short bad_constant); @@ -487,8 +491,6 @@ FieldLayoutInfo* info, TRAPS); - void update_class_name(Symbol* new_name); - public: ClassFileParser(ClassFileStream* stream, Symbol* name, @@ -496,12 +498,14 @@ Handle protection_domain, const InstanceKlass* unsafe_anonymous_host, GrowableArray* cp_patches, + const bool is_hidden, + const bool can_access_vm_annotations, Publicity pub_level, TRAPS); ~ClassFileParser(); - InstanceKlass* create_instance_klass(bool cf_changed_in_CFLH, TRAPS); + InstanceKlass* create_instance_klass(bool cf_changed_in_CFLH, const ClassInstanceInfo& cl_inst_info, TRAPS); const ClassFileStream* clone_stream() const; @@ -517,6 +521,7 @@ u2 this_class_index() const { return _this_class_index; } bool is_unsafe_anonymous() const { return _unsafe_anonymous_host != NULL; } + bool is_hidden() const { return _is_hidden; } bool is_interface() const { return _access_flags.is_interface(); } const InstanceKlass* unsafe_anonymous_host() const { return _unsafe_anonymous_host; } --- old/src/hotspot/share/classfile/classLoader.cpp 2019-12-03 19:36:34.000000000 -0800 +++ new/src/hotspot/share/classfile/classLoader.cpp 2019-12-03 19:36:34.000000000 -0800 @@ -1300,13 +1300,12 @@ ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); Handle protection_domain; + ClassLoadInfo cl_info(protection_domain); InstanceKlass* result = KlassFactory::create_from_stream(stream, name, loader_data, - protection_domain, - NULL, // unsafe_anonymous_host - NULL, // cp_patches + cl_info, THREAD); if (HAS_PENDING_EXCEPTION) { if (DumpSharedSpaces) { @@ -1348,8 +1347,8 @@ Arguments::assert_is_dumping_archive(); assert(stream != NULL, "sanity"); - if (ik->is_unsafe_anonymous()) { - // We do not archive unsafe anonymous classes. + if (ik->is_hidden() || ik->is_unsafe_anonymous()) { + // We do not archive hidden or unsafe anonymous classes. return; } --- old/src/hotspot/share/classfile/classLoaderData.cpp 2019-12-03 19:36:35.000000000 -0800 +++ new/src/hotspot/share/classfile/classLoaderData.cpp 2019-12-03 19:36:35.000000000 -0800 @@ -126,16 +126,16 @@ _name_and_id = SymbolTable::new_symbol(cl_instance_name_and_id); } -ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_unsafe_anonymous) : +ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_shortlived) : _metaspace(NULL), - _metaspace_lock(new Mutex(Mutex::leaf+1, "Metaspace allocation lock", true, - Mutex::_safepoint_check_never)), - _unloading(false), _is_unsafe_anonymous(is_unsafe_anonymous), + _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true, + Monitor::_safepoint_check_never)), + _unloading(false), _is_shortlived(is_shortlived), _modified_oops(true), _accumulated_modified_oops(false), // An unsafe anonymous class loader data doesn't have anything to keep // it from being unloaded during parsing of the unsafe anonymous class. // The null-class-loader should always be kept alive. - _keep_alive((is_unsafe_anonymous || h_class_loader.is_null()) ? 1 : 0), + _keep_alive((is_shortlived || h_class_loader.is_null()) ? 1 : 0), _claim(0), _handles(), _klasses(NULL), _packages(NULL), _modules(NULL), _unnamed_module(NULL), _dictionary(NULL), @@ -150,13 +150,13 @@ initialize_name(h_class_loader); } - if (!is_unsafe_anonymous) { - // The holder is initialized later for unsafe anonymous classes, and before calling anything - // that call class_loader(). + if (!is_shortlived) { + // The holder is initialized later for weak hidden and unsafe anonymous classes, + // and before calling anything that call class_loader(). initialize_holder(h_class_loader); - // A ClassLoaderData created solely for an unsafe anonymous class should never have a - // ModuleEntryTable or PackageEntryTable created for it. The defining package + // A ClassLoaderData created solely for an weak hidden or unsafe anonymous class should + // never have a ModuleEntryTable or PackageEntryTable created for it. The defining package // and module for an unsafe anonymous class will be found in its host class. _packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size); if (h_class_loader.is_null()) { @@ -291,20 +291,20 @@ } } -// Unsafe anonymous classes have their own ClassLoaderData that is marked to keep alive +// Weak hidden and unsafe anonymous classes have their own ClassLoaderData that is marked to keep alive // while the class is being parsed, and if the class appears on the module fixup list. -// Due to the uniqueness that no other class shares the unsafe anonymous class' name or -// ClassLoaderData, no other non-GC thread has knowledge of the unsafe anonymous class while +// Due to the uniqueness that no other class shares the hidden or unsafe anonymous class' name or +// ClassLoaderData, no other non-GC thread has knowledge of the hidden or unsafe anonymous class while // it is being defined, therefore _keep_alive is not volatile or atomic. void ClassLoaderData::inc_keep_alive() { - if (is_unsafe_anonymous()) { + if (is_shortlived()) { assert(_keep_alive > 0, "Invalid keep alive increment count"); _keep_alive++; } } void ClassLoaderData::dec_keep_alive() { - if (is_unsafe_anonymous()) { + if (is_shortlived()) { assert(_keep_alive > 0, "Invalid keep alive decrement count"); _keep_alive--; } @@ -411,20 +411,20 @@ // Do not need to record dependency if the dependency is to a class whose // class loader data is never freed. (i.e. the dependency's class loader // is one of the three builtin class loaders and the dependency is not - // unsafe anonymous.) + // short-lived.) if (to_cld->is_permanent_class_loader_data()) { return; } oop to; - if (to_cld->is_unsafe_anonymous()) { - // Just return if an unsafe anonymous class is attempting to record a dependency - // to itself. (Note that every unsafe anonymous class has its own unique class + if (to_cld->is_shortlived()) { + // Just return if a weak hidden or unsafe anonymous class is attempting to record a dependency + // to itself. (Note that every weak hidden or unsafe anonymous class has its own unique class // loader data.) if (to_cld == from_cld) { return; } - // Unsafe anonymous class dependencies are through the mirror. + // Hidden and unsafe anonymous class dependencies are through the mirror. to = k->java_mirror(); } else { to = to_cld->class_loader(); @@ -572,7 +572,7 @@ const int _default_loader_dictionary_size = 107; Dictionary* ClassLoaderData::create_dictionary() { - assert(!is_unsafe_anonymous(), "unsafe anonymous class loader data do not have a dictionary"); + assert(!is_shortlived(), "short lived class loader data do not have a dictionary"); int size; bool resizable = false; if (_the_null_class_loader_data == NULL) { @@ -618,7 +618,7 @@ // Unloading support bool ClassLoaderData::is_alive() const { - bool alive = keep_alive() // null class loader and incomplete unsafe anonymous klasses. + bool alive = keep_alive() // null class loader and incomplete weak hidden or unsafe anonymous klasses. || (_holder.peek() != NULL); // and not cleaned by the GC weak handle processing. return alive; @@ -716,13 +716,13 @@ // Returns true if this class loader data is for the app class loader // or a user defined system class loader. (Note that the class loader -// data may be unsafe anonymous.) +// data may be short-lived.) bool ClassLoaderData::is_system_class_loader_data() const { return SystemDictionary::is_system_class_loader(class_loader()); } // Returns true if this class loader data is for the platform class loader. -// (Note that the class loader data may be unsafe anonymous.) +// (Note that the class loader data may be short-lived.) bool ClassLoaderData::is_platform_class_loader_data() const { return SystemDictionary::is_platform_class_loader(class_loader()); } @@ -730,8 +730,8 @@ // Returns true if the class loader for this class loader data is one of // the 3 builtin (boot application/system or platform) class loaders, // including a user-defined system class loader. Note that if the class -// loader data is for an unsafe anonymous class then it may get freed by a GC -// even if its class loader is one of these loaders. +// loader data is for a weak hidden or unsafe anonymous class then it may +// get freed by a GC even if its class loader is one of these loaders. bool ClassLoaderData::is_builtin_class_loader_data() const { return (is_boot_class_loader_data() || SystemDictionary::is_system_class_loader(class_loader()) || @@ -740,9 +740,9 @@ // Returns true if this class loader data is a class loader data // that is not ever freed by a GC. It must be the CLD for one of the builtin -// class loaders and not the CLD for an unsafe anonymous class. +// class loaders and not the CLD for a weak hidden or unsafe anonymous class. bool ClassLoaderData::is_permanent_class_loader_data() const { - return is_builtin_class_loader_data() && !is_unsafe_anonymous(); + return is_builtin_class_loader_data() && !is_shortlived(); } ClassLoaderMetaspace* ClassLoaderData::metaspace_non_null() { @@ -759,8 +759,8 @@ if (this == the_null_class_loader_data()) { assert (class_loader() == NULL, "Must be"); metaspace = new ClassLoaderMetaspace(_metaspace_lock, Metaspace::BootMetaspaceType); - } else if (is_unsafe_anonymous()) { - metaspace = new ClassLoaderMetaspace(_metaspace_lock, Metaspace::UnsafeAnonymousMetaspaceType); + } else if (is_shortlived()) { + metaspace = new ClassLoaderMetaspace(_metaspace_lock, Metaspace::ShortLivedMetaspaceType); } else if (class_loader()->is_a(SystemDictionary::reflect_DelegatingClassLoader_klass())) { metaspace = new ClassLoaderMetaspace(_metaspace_lock, Metaspace::ReflectionMetaspaceType); } else { @@ -877,8 +877,8 @@ } } -// These CLDs are to contain unsafe anonymous classes used for JSR292 -ClassLoaderData* ClassLoaderData::unsafe_anonymous_class_loader_data(Handle loader) { +// These CLDs are to contain weak hidden or unsafe anonymous classes used for JSR292 +ClassLoaderData* ClassLoaderData::shortlived_class_loader_data(Handle loader) { // Add a new class loader data to the graph. return ClassLoaderDataGraph::add(loader, true); } @@ -920,8 +920,8 @@ // loader data: 0xsomeaddr of 'bootstrap' out->print("loader data: " INTPTR_FORMAT " of %s", p2i(this), loader_name_and_id()); } - if (is_unsafe_anonymous()) { - out->print(" unsafe anonymous"); + if (_is_shortlived) { + out->print(" short-lived"); } } @@ -931,7 +931,7 @@ void ClassLoaderData::print_on(outputStream* out) const { out->print("ClassLoaderData CLD: " PTR_FORMAT ", loader: " PTR_FORMAT ", loader_klass: %s {", p2i(this), p2i(_class_loader.ptr_raw()), loader_name_and_id()); - if (is_unsafe_anonymous()) out->print(" unsafe anonymous"); + if (is_shortlived()) out->print(" short-lived"); if (claimed()) out->print(" claimed"); if (is_unloading()) out->print(" unloading"); out->print(" metaspace: " INTPTR_FORMAT, p2i(metaspace_or_null())); @@ -951,8 +951,8 @@ assert_locked_or_safepoint(_metaspace_lock); oop cl = class_loader(); - guarantee(this == class_loader_data(cl) || is_unsafe_anonymous(), "Must be the same"); - guarantee(cl != NULL || this == ClassLoaderData::the_null_class_loader_data() || is_unsafe_anonymous(), "must be"); + guarantee(this == class_loader_data(cl) || is_shortlived(), "Must be the same"); + guarantee(cl != NULL || this == ClassLoaderData::the_null_class_loader_data() || is_shortlived(), "must be"); // Verify the integrity of the allocated space. if (metaspace_or_null() != NULL) { --- old/src/hotspot/share/classfile/classLoaderData.hpp 2019-12-03 19:36:36.000000000 -0800 +++ new/src/hotspot/share/classfile/classLoaderData.hpp 2019-12-03 19:36:36.000000000 -0800 @@ -117,17 +117,17 @@ // classes in the class loader are allocated. Mutex* _metaspace_lock; // Locks the metaspace for allocations and setup. bool _unloading; // true if this class loader goes away - bool _is_unsafe_anonymous; // CLD is dedicated to one class and that class determines the CLDs lifecycle. - // For example, an unsafe anonymous class. + bool _is_shortlived; // CLD is dedicated to one class and that class determines the CLDs lifecycle. + // For example, a weak hidden or an unsafe anonymous class. // Remembered sets support for the oops in the class loader data. bool _modified_oops; // Card Table Equivalent (YC/CMS support) bool _accumulated_modified_oops; // Mod Union Equivalent (CMS support) int _keep_alive; // if this CLD is kept alive. - // Used for unsafe anonymous classes and the boot class - // loader. _keep_alive does not need to be volatile or - // atomic since there is one unique CLD per unsafe anonymous class. + // Used for weak hidden classes, unsafe anonymous classes and the + // boot class loader. _keep_alive does not need to be volatile or + // atomic since there is one unique CLD per weak hidden or unsafe anonymous class. volatile int _claim; // non-zero if claimed, for example during GC traces. // To avoid applying oop closure more than once. @@ -162,7 +162,7 @@ void set_next(ClassLoaderData* next) { _next = next; } ClassLoaderData* next() const { return Atomic::load(&_next); } - ClassLoaderData(Handle h_class_loader, bool is_unsafe_anonymous); + ClassLoaderData(Handle h_class_loader, bool is_shortlived); ~ClassLoaderData(); // The CLD are not placed in the Heap, so the Card Table or @@ -231,7 +231,7 @@ Mutex* metaspace_lock() const { return _metaspace_lock; } - bool is_unsafe_anonymous() const { return _is_unsafe_anonymous; } + bool is_shortlived() const { return _is_shortlived; } static void init_null_class_loader_data(); @@ -240,15 +240,15 @@ } // Returns true if this class loader data is for the system class loader. - // (Note that the class loader data may be unsafe anonymous.) + // (Note that the class loader data may be for an weak hidden or unsafe anonymous class) bool is_system_class_loader_data() const; // Returns true if this class loader data is for the platform class loader. - // (Note that the class loader data may be unsafe anonymous.) + // (Note that the class loader data may be for an weak hidden or unsafe anonymous class) bool is_platform_class_loader_data() const; // Returns true if this class loader data is for the boot class loader. - // (Note that the class loader data may be unsafe anonymous.) + // (Note that the class loader data may be for an weak hidden unsafe anonymous class) inline bool is_boot_class_loader_data() const; bool is_builtin_class_loader_data() const; @@ -269,7 +269,7 @@ return _unloading; } - // Used to refcount an unsafe anonymous class's CLD in order to + // Used to refcount an weak hidden or unsafe anonymous class's CLD in order to // indicate their aliveness. void inc_keep_alive(); void dec_keep_alive(); @@ -313,7 +313,7 @@ static ClassLoaderData* class_loader_data(oop loader); static ClassLoaderData* class_loader_data_or_null(oop loader); - static ClassLoaderData* unsafe_anonymous_class_loader_data(Handle loader); + static ClassLoaderData* shortlived_class_loader_data(Handle loader); // Returns Klass* of associated class loader, or NULL if associated loader is 'bootstrap'. // Also works if unloading. --- old/src/hotspot/share/classfile/classLoaderDataGraph.cpp 2019-12-03 19:36:37.000000000 -0800 +++ new/src/hotspot/share/classfile/classLoaderDataGraph.cpp 2019-12-03 19:36:37.000000000 -0800 @@ -192,7 +192,7 @@ // Add a new class loader data node to the list. Assign the newly created // ClassLoaderData into the java/lang/ClassLoader object as a hidden field -ClassLoaderData* ClassLoaderDataGraph::add_to_graph(Handle loader, bool is_unsafe_anonymous) { +ClassLoaderData* ClassLoaderDataGraph::add_to_graph(Handle loader, bool is_shortlived) { assert_lock_strong(ClassLoaderDataGraph_lock); @@ -200,7 +200,7 @@ // First check if another thread beat us to creating the CLD and installing // it into the loader while we were waiting for the lock. - if (!is_unsafe_anonymous && loader.not_null()) { + if (!is_shortlived && loader.not_null()) { cld = java_lang_ClassLoader::loader_data_acquire(loader()); if (cld != NULL) { return cld; @@ -212,14 +212,14 @@ // loader oop in all collections, particularly young collections. NoSafepointVerifier no_safepoints; - cld = new ClassLoaderData(loader, is_unsafe_anonymous); + cld = new ClassLoaderData(loader, is_shortlived); // First install the new CLD to the Graph. cld->set_next(_head); Atomic::release_store(&_head, cld); // Next associate with the class_loader. - if (!is_unsafe_anonymous) { + if (!is_shortlived) { // Use OrderAccess, since readers need to get the loader_data only after // it's added to the Graph java_lang_ClassLoader::release_set_loader_data(loader(), cld); @@ -237,9 +237,9 @@ return cld; } -ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_unsafe_anonymous) { +ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_shortlived) { MutexLocker ml(ClassLoaderDataGraph_lock); - ClassLoaderData* loader_data = add_to_graph(loader, is_unsafe_anonymous); + ClassLoaderData* loader_data = add_to_graph(loader, is_shortlived); return loader_data; } --- old/src/hotspot/share/classfile/classLoaderDataGraph.hpp 2019-12-03 19:36:38.000000000 -0800 +++ new/src/hotspot/share/classfile/classLoaderDataGraph.hpp 2019-12-03 19:36:38.000000000 -0800 @@ -56,8 +56,8 @@ static volatile size_t _num_instance_classes; static volatile size_t _num_array_classes; - static ClassLoaderData* add_to_graph(Handle class_loader, bool is_unsafe_anonymous); - static ClassLoaderData* add(Handle class_loader, bool is_unsafe_anonymous); + static ClassLoaderData* add_to_graph(Handle class_loader, bool is_shortlived); + static ClassLoaderData* add(Handle class_loader, bool is_shortlived); public: static ClassLoaderData* find_or_create(Handle class_loader); @@ -76,7 +76,7 @@ // Walking classes through the ClassLoaderDataGraph include array classes. It also includes // classes that are allocated but not loaded, classes that have errors, and scratch classes // for redefinition. These classes are removed during the next class unloading. - // Walking the ClassLoaderDataGraph also includes unsafe anonymous classes. + // Walking the ClassLoaderDataGraph also includes hidden and unsafe anonymous classes. static void classes_do(KlassClosure* klass_closure); static void classes_do(void f(Klass* const)); static void methods_do(void f(Method*)); --- old/src/hotspot/share/classfile/classLoaderExt.cpp 2019-12-03 19:36:39.000000000 -0800 +++ new/src/hotspot/share/classfile/classLoaderExt.cpp 2019-12-03 19:36:39.000000000 -0800 @@ -284,13 +284,12 @@ ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); Handle protection_domain; + ClassLoadInfo cl_info(protection_domain); InstanceKlass* result = KlassFactory::create_from_stream(stream, name, loader_data, - protection_domain, - NULL, // unsafe_anonymous_host - NULL, // cp_patches + cl_info, THREAD); if (HAS_PENDING_EXCEPTION) { --- old/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp 2019-12-03 19:36:40.000000000 -0800 +++ new/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp 2019-12-03 19:36:40.000000000 -0800 @@ -129,7 +129,7 @@ class LoaderTreeNode : public ResourceObj { - // We walk the CLDG and, for each CLD which is non-unsafe_anonymous, add + // We walk the CLDG and, for each CLD which is findable, add // a tree node. // To add a node we need its parent node; if the parent node does not yet // exist - because we have not yet encountered the CLD for the parent loader - @@ -220,7 +220,7 @@ if (print_classes) { if (_classes != NULL) { for (LoadedClassInfo* lci = _classes; lci; lci = lci->_next) { - // Non-unsafe anonymous classes should live in the primary CLD of its loader + // Hidden and unsafe anonymous classes should live in the primary CLD of its loader assert(lci->_cld == _cld, "must be"); branchtracker.print(st); @@ -258,7 +258,7 @@ st->print("%*s ", indentation, ""); } st->print("%s", lci->_klass->external_name()); - // For unsafe anonymous classes, also print CLD if verbose. Should be a different one than the primary CLD. + // For hidden and unsafe anonymous classes, also print CLD if verbose. Should be a different one than the primary CLD. assert(lci->_cld != _cld, "must be"); if (verbose) { st->print(" (Loader Data: " PTR_FORMAT ")", p2i(lci->_cld)); @@ -319,14 +319,14 @@ _next = info; } - void add_classes(LoadedClassInfo* first_class, int num_classes, bool is_unsafe_anonymous) { - LoadedClassInfo** p_list_to_add_to = is_unsafe_anonymous ? &_anon_classes : &_classes; + void add_classes(LoadedClassInfo* first_class, int num_classes, bool is_hidden) { + LoadedClassInfo** p_list_to_add_to = is_hidden ? &_anon_classes : &_classes; // Search tail. while ((*p_list_to_add_to) != NULL) { p_list_to_add_to = &(*p_list_to_add_to)->_next; } *p_list_to_add_to = first_class; - if (is_unsafe_anonymous) { + if (is_hidden) { _num_anon_classes += num_classes; } else { _num_classes += num_classes; @@ -421,7 +421,7 @@ LoadedClassCollectClosure lccc(cld); const_cast(cld)->classes_do(&lccc); if (lccc._num_classes > 0) { - info->add_classes(lccc._list, lccc._num_classes, cld->is_unsafe_anonymous()); + info->add_classes(lccc._list, lccc._num_classes, cld->is_shortlived()); } } @@ -481,7 +481,7 @@ assert(info != NULL, "must be"); // Update CLD in node, but only if this is the primary CLD for this loader. - if (cld->is_unsafe_anonymous() == false) { + if (cld->is_shortlived() == false) { assert(info->cld() == NULL, "there should be only one primary CLD per loader"); info->set_cld(cld); } --- old/src/hotspot/share/classfile/classLoaderStats.cpp 2019-12-03 19:36:41.000000000 -0800 +++ new/src/hotspot/share/classfile/classLoaderStats.cpp 2019-12-03 19:36:41.000000000 -0800 @@ -59,7 +59,7 @@ cls = *cls_ptr; } - if (!cld->is_unsafe_anonymous()) { + if (!cld->is_shortlived()) { cls->_cld = cld; } @@ -71,7 +71,7 @@ ClassStatsClosure csc; cld->classes_do(&csc); - if(cld->is_unsafe_anonymous()) { + if(cld->is_shortlived()) { cls->_anon_classes_count += csc._num_classes; } else { cls->_classes_count = csc._num_classes; @@ -80,7 +80,7 @@ ClassLoaderMetaspace* ms = cld->metaspace_or_null(); if (ms != NULL) { - if(cld->is_unsafe_anonymous()) { + if(cld->is_shortlived()) { cls->_anon_chunk_sz += ms->allocated_chunks_bytes(); cls->_anon_block_sz += ms->allocated_blocks_bytes(); } else { --- old/src/hotspot/share/classfile/defaultMethods.cpp 2019-12-03 19:36:42.000000000 -0800 +++ new/src/hotspot/share/classfile/defaultMethods.cpp 2019-12-03 19:36:42.000000000 -0800 @@ -919,7 +919,7 @@ ConstantPool* cp = bpool->create_constant_pool(CHECK); if (cp != klass->constants()) { // Copy resolved anonymous class into new constant pool. - if (klass->is_unsafe_anonymous()) { + if (klass->is_unsafe_anonymous() || klass->is_hidden()) { cp->klass_at_put(klass->this_class_index(), klass); } klass->class_loader_data()->add_to_deallocate_list(klass->constants()); --- old/src/hotspot/share/classfile/javaClasses.cpp 2019-12-03 19:36:43.000000000 -0800 +++ new/src/hotspot/share/classfile/javaClasses.cpp 2019-12-03 19:36:42.000000000 -0800 @@ -851,12 +851,13 @@ k->clear_has_raw_archived_mirror(); } } - create_mirror(k, Handle(), Handle(), Handle(), CHECK); + create_mirror(k, Handle(), Handle(), Handle(), Handle(), CHECK); } void java_lang_Class::initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain, + Handle classData, TRAPS) { // Allocate a simple java object for a lock. // This needs to be a java object because during class initialization @@ -869,6 +870,9 @@ // Initialize static fields InstanceKlass::cast(k)->do_local_static_fields(&initialize_static_field, mirror, CHECK); + + // Set classData + set_class_data(mirror(), classData()); } // Set the java.lang.Module module field in the java_lang_Class mirror @@ -922,7 +926,8 @@ } void java_lang_Class::create_mirror(Klass* k, Handle class_loader, - Handle module, Handle protection_domain, TRAPS) { + Handle module, Handle protection_domain, + Handle classData, TRAPS) { assert(k != NULL, "Use create_basic_type_mirror for primitive types"); assert(k->java_mirror() == NULL, "should only assign mirror once"); @@ -969,7 +974,7 @@ } else { assert(k->is_instance_klass(), "Must be"); - initialize_mirror_fields(k, mirror, protection_domain, THREAD); + initialize_mirror_fields(k, mirror, protection_domain, classData, THREAD); if (HAS_PENDING_EXCEPTION) { // If any of the fields throws an exception like OOM remove the klass field // from the mirror so GC doesn't follow it after the klass has been deallocated. @@ -1394,6 +1399,15 @@ java_class->obj_field_put(_signers_offset, (oop)signers); } +oop java_lang_Class::class_data(oop java_class) { + assert(_classData_offset != 0, "must be set"); + return java_class->obj_field(_classData_offset); +} +void java_lang_Class::set_class_data(oop java_class, oop class_data) { + assert(_classData_offset != 0, "must be set"); + java_class->obj_field_put(_classData_offset, class_data); +} + void java_lang_Class::set_class_loader(oop java_class, oop loader) { // jdk7 runs Queens in bootstrapping and jdk8-9 has no coordinated pushes yet. @@ -4208,6 +4222,7 @@ int java_lang_Class::_signers_offset; int java_lang_Class::_name_offset; int java_lang_Class::_source_file_offset; +int java_lang_Class::_classData_offset; GrowableArray* java_lang_Class::_fixup_mirror_list = NULL; GrowableArray* java_lang_Class::_fixup_module_field_list = NULL; int java_lang_Throwable::backtrace_offset; --- old/src/hotspot/share/classfile/javaClasses.hpp 2019-12-03 19:36:44.000000000 -0800 +++ new/src/hotspot/share/classfile/javaClasses.hpp 2019-12-03 19:36:43.000000000 -0800 @@ -237,6 +237,7 @@ macro(java_lang_Class, protection_domain, object_signature, false) \ macro(java_lang_Class, signers, object_signature, false) \ macro(java_lang_Class, source_file, object_signature, false) \ + macro(java_lang_Class, classData, object_signature, false) class java_lang_Class : AllStatic { friend class VMStructs; @@ -259,6 +260,7 @@ static int _component_mirror_offset; static int _name_offset; static int _source_file_offset; + static int _classData_offset; static bool offsets_computed; static int classRedefinedCount_offset; @@ -270,7 +272,8 @@ static void set_protection_domain(oop java_class, oop protection_domain); static void set_class_loader(oop java_class, oop class_loader); static void set_component_mirror(oop java_class, oop comp_mirror); - static void initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain, TRAPS); + static void initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain, + Handle classData, TRAPS); static void set_mirror_module_field(Klass* K, Handle mirror, Handle module, TRAPS); public: static void allocate_fixup_lists(); @@ -278,7 +281,7 @@ // Instance creation static void create_mirror(Klass* k, Handle class_loader, Handle module, - Handle protection_domain, TRAPS); + Handle protection_domain, Handle classData, TRAPS); static void fixup_mirror(Klass* k, TRAPS); static oop create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS); static void update_archived_primitive_mirror_native_pointers(oop archived_mirror) NOT_CDS_JAVA_HEAP_RETURN; @@ -326,6 +329,8 @@ static oop component_mirror(oop java_class); static objArrayOop signers(oop java_class); static void set_signers(oop java_class, objArrayOop signers); + static oop class_data(oop java_class); + static void set_class_data(oop java_class, oop classData); static oop class_loader(oop java_class); static void set_module(oop java_class, oop module); @@ -1138,16 +1143,20 @@ // Relevant integer codes (keep these in synch. with MethodHandleNatives.Constants): enum { - MN_IS_METHOD = 0x00010000, // method (not constructor) - MN_IS_CONSTRUCTOR = 0x00020000, // constructor - MN_IS_FIELD = 0x00040000, // field - MN_IS_TYPE = 0x00080000, // nested type - MN_CALLER_SENSITIVE = 0x00100000, // @CallerSensitive annotation detected - MN_REFERENCE_KIND_SHIFT = 24, // refKind - MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT, + MN_IS_METHOD = 0x00010000, // method (not constructor) + MN_IS_CONSTRUCTOR = 0x00020000, // constructor + MN_IS_FIELD = 0x00040000, // field + MN_IS_TYPE = 0x00080000, // nested type + MN_CALLER_SENSITIVE = 0x00100000, // @CallerSensitive annotation detected + MN_REFERENCE_KIND_SHIFT = 24, // refKind + MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT, // The SEARCH_* bits are not for MN.flags but for the matchFlags argument of MHN.getMembers: - MN_SEARCH_SUPERCLASSES = 0x00100000, // walk super classes - MN_SEARCH_INTERFACES = 0x00200000 // walk implemented interfaces + MN_SEARCH_SUPERCLASSES = 0x00100000, // walk super classes + MN_SEARCH_INTERFACES = 0x00200000, // walk implemented interfaces + MN_NESTMATE_CLASS = 0x00000001, + MN_HIDDEN_CLASS = 0x00000002, + MN_WEAK_CLASS = 0x00000004, + MN_ACCESS_VM_ANNOTATIONS = 0x00100000 }; // Accessors for code generation: --- old/src/hotspot/share/classfile/klassFactory.cpp 2019-12-03 19:36:44.000000000 -0800 +++ new/src/hotspot/share/classfile/klassFactory.cpp 2019-12-03 19:36:44.000000000 -0800 @@ -83,12 +83,17 @@ class_name, loader_data, protection_domain, - NULL, - NULL, + NULL, // unsafe_anonymous_host + NULL, // cp_patches + false, // is_hidden + false, // can_access_vm_annotations ClassFileParser::BROADCAST, // publicity level CHECK_NULL); - InstanceKlass* new_ik = parser.create_instance_klass(true /* changed_by_loadhook */, + ClassInstanceInfo cl_inst_info; + InstanceKlass* new_ik = parser.create_instance_klass(true, // changed_by_loadhook + cl_inst_info, // dynamic_nest_host and classData CHECK_NULL); + if (cached_class_file != NULL) { new_ik->set_cached_class_file(cached_class_file); } @@ -166,9 +171,7 @@ InstanceKlass* KlassFactory::create_from_stream(ClassFileStream* stream, Symbol* name, ClassLoaderData* loader_data, - Handle protection_domain, - const InstanceKlass* unsafe_anonymous_host, - GrowableArray* cp_patches, + const ClassLoadInfo& cl_info, TRAPS) { assert(stream != NULL, "invariant"); assert(loader_data != NULL, "invariant"); @@ -184,12 +187,15 @@ // increment counter THREAD->statistical_info().incr_define_class_count(); - // Skip this processing for VM anonymous classes - if (unsafe_anonymous_host == NULL) { + assert(!(cl_info.is_hidden() && (cl_info.unsafe_anonymous_host() != NULL)), + "hidden class has an anonymous host"); + + // Skip this processing for VM hidden or anonymous classes + if (!cl_info.is_hidden() && (cl_info.unsafe_anonymous_host() == NULL)) { stream = check_class_file_load_hook(stream, name, loader_data, - protection_domain, + cl_info.protection_domain(), &cached_class_file, CHECK_NULL); } @@ -197,14 +203,21 @@ ClassFileParser parser(stream, name, loader_data, - protection_domain, - unsafe_anonymous_host, - cp_patches, + cl_info.protection_domain(), + cl_info.unsafe_anonymous_host(), + cl_info.cp_patches(), + cl_info.is_hidden(), + cl_info.can_access_vm_annotations(), ClassFileParser::BROADCAST, // publicity level CHECK_NULL); - InstanceKlass* result = parser.create_instance_klass(old_stream != stream, CHECK_NULL); - assert(result == parser.create_instance_klass(old_stream != stream, THREAD), "invariant"); + const ClassInstanceInfo* cl_inst_info = cl_info.class_hidden_info_ptr(); + InstanceKlass* result = parser.create_instance_klass(old_stream != stream, *cl_inst_info, CHECK_NULL); +#ifdef ASSERT + // Need a NULL dynamic_nest_host here otherwise set_nest_host() may assert. + ClassInstanceInfo cl_inst_info_null(NULL, cl_inst_info->class_data()); + assert(result == parser.create_instance_klass(old_stream != stream, cl_inst_info_null, THREAD), "invariant"); +#endif if (result == NULL) { return NULL; --- old/src/hotspot/share/classfile/klassFactory.hpp 2019-12-03 19:36:45.000000000 -0800 +++ new/src/hotspot/share/classfile/klassFactory.hpp 2019-12-03 19:36:45.000000000 -0800 @@ -30,6 +30,7 @@ class ClassFileStream; class ClassLoaderData; +class ClassLoadInfo; template class GrowableArray; class Klass; @@ -71,9 +72,7 @@ static InstanceKlass* create_from_stream(ClassFileStream* stream, Symbol* name, ClassLoaderData* loader_data, - Handle protection_domain, - const InstanceKlass* unsafe_anonymous_host, - GrowableArray* cp_patches, + const ClassLoadInfo& cl_info, TRAPS); public: static InstanceKlass* check_shared_class_file_load_hook( --- old/src/hotspot/share/classfile/moduleEntry.hpp 2019-12-03 19:36:46.000000000 -0800 +++ new/src/hotspot/share/classfile/moduleEntry.hpp 2019-12-03 19:36:46.000000000 -0800 @@ -110,7 +110,7 @@ ClassLoaderData* loader_data() const { return _loader_data; } void set_loader_data(ClassLoaderData* cld) { - assert(!cld->is_unsafe_anonymous(), "Unexpected unsafe anonymous class loader data"); + assert(!cld->is_shortlived(), "Unexpected short-lived class loader data"); _loader_data = cld; } --- old/src/hotspot/share/classfile/systemDictionary.cpp 2019-12-03 19:36:47.000000000 -0800 +++ new/src/hotspot/share/classfile/systemDictionary.cpp 2019-12-03 19:36:47.000000000 -0800 @@ -112,6 +112,46 @@ 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_weak_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_weak_hidden = false; + _can_access_vm_annotations = false; +} + +ClassLoadInfo::ClassLoadInfo(Handle protection_domain, + const InstanceKlass* unsafe_anonymous_host, + GrowableArray* cp_patches, + InstanceKlass* dynamic_nest_host, + Handle class_data, + bool is_hidden, + bool is_weak_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_weak_hidden = is_weak_hidden; + _can_access_vm_annotations = can_access_vm_annotations; +} + // ---------------------------------------------------------------------------- // Java-level SystemLoader and PlatformLoader @@ -982,24 +1022,34 @@ // 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* 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); + + if (cl_info.unsafe_anonymous_host() != NULL) { + // - for unsafe anonymous class: create a new short-lived CLD 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::shortlived_class_loader_data(class_loader); + } else if (cl_info.is_hidden()) { + // - for weak hidden class: create a new short-lived CLD whose loader is + // the Lookup class' loader. + // - for hidden class: add the class to the Lookup class' loader's CLD. + if (cl_info.is_weak_hidden()) { + loader_data = ClassLoaderData::shortlived_class_loader_data(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 +1065,15 @@ 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) + if ((cl_info.is_hidden() || (cl_info.unsafe_anonymous_host() != NULL)) && k != NULL) { + // Weak hidden and unsafe anonymous classes must update ClassLoaderData holder // 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_weak_hidden() || (cl_info.unsafe_anonymous_host() != NULL)) { + k->class_loader_data()->initialize_holder(Handle(THREAD, k->java_mirror())); + } { MutexLocker mu_r(Compile_lock, THREAD); @@ -1036,12 +1086,14 @@ // 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 (cl_info.unsafe_anonymous_host() != NULL) { + k->eager_initialize(CHECK_NULL); + } // notify jvmti if (JvmtiExport::should_post_class_load()) { @@ -1052,7 +1104,7 @@ post_class_load_event(&class_load_start_event, k, loader_data); } } - assert(unsafe_anonymous_host != NULL || NULL == cp_patches, + assert(cl_info.unsafe_anonymous_host() != NULL || NULL == cl_info.cp_patches(), "cp_patches only found with unsafe_anonymous_host"); return k; @@ -1107,13 +1159,8 @@ 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"); --- old/src/hotspot/share/classfile/systemDictionary.hpp 2019-12-03 19:36:48.000000000 -0800 +++ new/src/hotspot/share/classfile/systemDictionary.hpp 2019-12-03 19:36:48.000000000 -0800 @@ -34,6 +34,53 @@ #include "runtime/signature.hpp" #include "utilities/hashtable.hpp" +class ClassInstanceInfo : public StackObj { + private: + InstanceKlass* _dynamic_nest_host; + Handle _class_data; + + public: + ClassInstanceInfo() { + _dynamic_nest_host = NULL; + _class_data = Handle(); + } + ClassInstanceInfo(InstanceKlass* dynamic_nest_host, Handle class_data) { + _dynamic_nest_host = dynamic_nest_host; + _class_data = class_data; + } + + InstanceKlass* dynamic_nest_host() const { return _dynamic_nest_host; } + Handle class_data() const { return _class_data; } + friend class ClassLoadInfo; +}; + +class ClassLoadInfo : public StackObj { + private: + Handle _protection_domain; + const InstanceKlass* _unsafe_anonymous_host; + GrowableArray* _cp_patches; + ClassInstanceInfo _class_hidden_info; + bool _is_hidden; + bool _is_weak_hidden; + bool _can_access_vm_annotations; + + public: + ClassLoadInfo(); + ClassLoadInfo(Handle protection_domain); + ClassLoadInfo(Handle protection_domain, const InstanceKlass* unsafe_anonymous_host, + GrowableArray* cp_patches, InstanceKlass* dynamic_nest_host, + Handle class_data, bool is_hidden, bool is_weak_hidden, + bool can_access_vm_annotations); + + Handle protection_domain() const { return _protection_domain; } + const InstanceKlass* unsafe_anonymous_host() const { return _unsafe_anonymous_host; } + GrowableArray* cp_patches() const { return _cp_patches; } + const ClassInstanceInfo* class_hidden_info_ptr() const { return &_class_hidden_info; } + bool is_hidden() const { return _is_hidden; } + bool is_weak_hidden() const { return _is_weak_hidden; } + bool can_access_vm_annotations() const { return _can_access_vm_annotations; } +}; + // The dictionary in each ClassLoaderData stores all loaded classes, either // initiatied by its class loader or defined by its class loader: // @@ -268,28 +315,10 @@ bool is_superclass, TRAPS); - // Parse new stream. This won't update the dictionary or - // class hierarchy, simply parse the stream. Used by JVMTI RedefineClasses. - // Also used by Unsafe_DefineAnonymousClass - static InstanceKlass* parse_stream(Symbol* class_name, - Handle class_loader, - Handle protection_domain, - ClassFileStream* st, - TRAPS) { - return parse_stream(class_name, - class_loader, - protection_domain, - st, - NULL, // unsafe_anonymous_host - NULL, // cp_patches - THREAD); - } static InstanceKlass* parse_stream(Symbol* class_name, Handle class_loader, - Handle protection_domain, ClassFileStream* st, - const InstanceKlass* unsafe_anonymous_host, - GrowableArray* cp_patches, + const ClassLoadInfo& cl_info, TRAPS); // Resolve from stream (called by jni_DefineClass and JVM_DefineClass) --- old/src/hotspot/share/classfile/systemDictionaryShared.cpp 2019-12-03 19:36:49.000000000 -0800 +++ new/src/hotspot/share/classfile/systemDictionaryShared.cpp 2019-12-03 19:36:49.000000000 -0800 @@ -899,7 +899,7 @@ if (!UseSharedSpaces) { return NULL; } - if (class_name == NULL) { // don't do this for anonymous classes + if (class_name == NULL) { // don't do this for hidden and unsafe anonymous classes return NULL; } if (class_loader.is_null() || @@ -1078,9 +1078,9 @@ } bool SystemDictionaryShared::should_be_excluded(InstanceKlass* k) { - if (k->class_loader_data()->is_unsafe_anonymous()) { - warn_excluded(k, "Unsafe anonymous class"); - return true; // unsafe anonymous classes are not archived, skip + if (k->is_hidden() || k->is_unsafe_anonymous()) { + warn_excluded(k, "Hidden or Unsafe anonymous class"); + return true; // hidden and unsafe anonymous classes are not archived, skip } if (k->is_in_error_state()) { warn_excluded(k, "In error state"); --- old/src/hotspot/share/classfile/vmSymbols.cpp 2019-12-03 19:36:50.000000000 -0800 +++ new/src/hotspot/share/classfile/vmSymbols.cpp 2019-12-03 19:36:49.000000000 -0800 @@ -560,6 +560,7 @@ case vmIntrinsics::_isInterface: case vmIntrinsics::_isArray: case vmIntrinsics::_isPrimitive: + case vmIntrinsics::_isHiddenClass: case vmIntrinsics::_getSuperclass: case vmIntrinsics::_Class_cast: case vmIntrinsics::_getLength: --- old/src/hotspot/share/classfile/vmSymbols.hpp 2019-12-03 19:36:51.000000000 -0800 +++ new/src/hotspot/share/classfile/vmSymbols.hpp 2019-12-03 19:36:50.000000000 -0800 @@ -424,6 +424,7 @@ template(protection_domain_name, "protection_domain") \ template(signers_name, "signers_name") \ template(source_file_name, "source_file") \ + template(classData_name, "classData_name") \ template(loader_data_name, "loader_data") \ template(vmdependencies_name, "vmdependencies") \ template(last_cleanup_name, "last_cleanup") \ @@ -879,6 +880,8 @@ do_name( isArray_name, "isArray") \ do_intrinsic(_isPrimitive, java_lang_Class, isPrimitive_name, void_boolean_signature, F_RN) \ do_name( isPrimitive_name, "isPrimitive") \ + do_intrinsic(_isHiddenClass, java_lang_Class, isHiddenClass_name, void_boolean_signature, F_RN) \ + do_name( isHiddenClass_name, "isHiddenClass") \ do_intrinsic(_getSuperclass, java_lang_Class, getSuperclass_name, void_class_signature, F_RN) \ do_name( getSuperclass_name, "getSuperclass") \ do_intrinsic(_Class_cast, java_lang_Class, Class_cast_name, object_object_signature, F_R) \ --- old/src/hotspot/share/include/jvm.h 2019-12-03 19:36:52.000000000 -0800 +++ new/src/hotspot/share/include/jvm.h 2019-12-03 19:36:51.000000000 -0800 @@ -389,6 +389,22 @@ const char *source); /* + * Define a class with the specified lookup class. + * lookup: Lookup class + * name: the name of the class + * loader: defining class loader + * buf: class bytes + * len: length of class bytes + * pd: protection domain + * init: initialize the class + * flags: properties of the class + * classData: private static pre-initialized field; may be null + */ +JNIEXPORT jclass JNICALL +JVM_LookupDefineClass(JNIEnv *env, jclass lookup, const char *name, jobject loader, + const jbyte *buf, jsize len, jobject pd, jboolean init, int flags, jobject classData); + +/* * Module support funcions */ @@ -474,6 +490,9 @@ JNIEXPORT jboolean JNICALL JVM_IsPrimitiveClass(JNIEnv *env, jclass cls); +JNIEXPORT jboolean JNICALL +JVM_IsHiddenClass(JNIEnv *env, jclass cls); + JNIEXPORT jint JNICALL JVM_GetClassModifiers(JNIEnv *env, jclass cls); --- old/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp 2019-12-03 19:36:52.000000000 -0800 +++ new/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp 2019-12-03 19:36:52.000000000 -0800 @@ -1464,8 +1464,10 @@ class_name, cld, pd, - NULL, // host klass - NULL, // cp_patches + NULL, // host klass + NULL, // cp_patches + false, // is_hidden + false, // can_access_vm_annotations ClassFileParser::INTERNAL, // internal visibility THREAD); if (HAS_PENDING_EXCEPTION) { @@ -1473,7 +1475,8 @@ CLEAR_PENDING_EXCEPTION; return NULL; } - InstanceKlass* const new_ik = new_parser.create_instance_klass(false, THREAD); + ClassInstanceInfo cl_inst_info; + InstanceKlass* const new_ik = new_parser.create_instance_klass(false, cl_inst_info, THREAD); if (HAS_PENDING_EXCEPTION) { log_pending_exception(PENDING_EXCEPTION); CLEAR_PENDING_EXCEPTION; --- old/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp 2019-12-03 19:36:53.000000000 -0800 +++ new/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp 2019-12-03 19:36:53.000000000 -0800 @@ -137,7 +137,6 @@ static traceid cld_id(CldPtr cld, bool leakp) { assert(cld != NULL, "invariant"); - assert(!cld->is_unsafe_anonymous(), "invariant"); if (leakp) { SET_LEAKP(cld); } else { @@ -514,7 +513,6 @@ static int write_classloader(JfrCheckpointWriter* writer, CldPtr cld, bool leakp) { assert(cld != NULL, "invariant"); - assert(!cld->is_unsafe_anonymous(), "invariant"); // class loader type const Klass* class_loader_klass = cld->class_loader_klass(); if (class_loader_klass == NULL) { @@ -572,7 +570,7 @@ CLDCallback() {} void do_cld(ClassLoaderData* cld) { assert(cld != NULL, "invariant"); - if (cld->is_unsafe_anonymous()) { + if (cld->is_shortlived()) { return; } do_class_loader_data(cld); --- old/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp 2019-12-03 19:36:54.000000000 -0800 +++ new/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.cpp 2019-12-03 19:36:54.000000000 -0800 @@ -140,7 +140,7 @@ void JfrTraceId::assign(const ClassLoaderData* cld) { assert(cld != NULL, "invariant"); - if (cld->is_unsafe_anonymous()) { + if (cld->is_shortlived()) { cld->set_trace_id(0); return; } --- old/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp 2019-12-03 19:36:56.000000000 -0800 +++ new/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp 2019-12-03 19:36:55.000000000 -0800 @@ -94,7 +94,7 @@ inline traceid JfrTraceId::use(const ClassLoaderData* cld) { assert(cld != NULL, "invariant"); - return cld->is_unsafe_anonymous() ? 0 : set_used_and_get(cld); + return cld->is_shortlived() ? 0 : set_used_and_get(cld); } inline void JfrTraceId::set_leakp(const Method* method) { --- old/src/hotspot/share/memory/metaspace.cpp 2019-12-03 19:36:57.000000000 -0800 +++ new/src/hotspot/share/memory/metaspace.cpp 2019-12-03 19:36:56.000000000 -0800 @@ -64,7 +64,7 @@ switch (t) { case Metaspace::StandardMetaspaceType: s = "Standard"; break; case Metaspace::BootMetaspaceType: s = "Boot"; break; - case Metaspace::UnsafeAnonymousMetaspaceType: s = "UnsafeAnonymous"; break; + case Metaspace::ShortLivedMetaspaceType: s = "ShortLived"; break; case Metaspace::ReflectionMetaspaceType: s = "Reflection"; break; default: ShouldNotReachHere(); } --- old/src/hotspot/share/memory/metaspace.hpp 2019-12-03 19:36:58.000000000 -0800 +++ new/src/hotspot/share/memory/metaspace.hpp 2019-12-03 19:36:57.000000000 -0800 @@ -104,8 +104,8 @@ ZeroMetaspaceType = 0, StandardMetaspaceType = ZeroMetaspaceType, BootMetaspaceType = StandardMetaspaceType + 1, - UnsafeAnonymousMetaspaceType = BootMetaspaceType + 1, - ReflectionMetaspaceType = UnsafeAnonymousMetaspaceType + 1, + ShortLivedMetaspaceType = BootMetaspaceType + 1, + ReflectionMetaspaceType = ShortLivedMetaspaceType + 1, MetaspaceTypeCount }; @@ -245,7 +245,7 @@ // Initialize the first chunk for a Metaspace. Used for // special cases such as the boot class loader, reflection - // class loader and anonymous class loader. + // class loader and hidden class loader. void initialize_first_chunk(Metaspace::MetaspaceType type, Metaspace::MetadataType mdtype); metaspace::Metachunk* get_initialization_chunk(Metaspace::MetaspaceType type, Metaspace::MetadataType mdtype); @@ -390,7 +390,7 @@ rf_show_loaders = (1 << 0), // Breaks report down by chunk type (small, medium, ...). rf_break_down_by_chunktype = (1 << 1), - // Breaks report down by space type (anonymous, reflection, ...). + // Breaks report down by space type (hidden, reflection, ...). rf_break_down_by_spacetype = (1 << 2), // Print details about the underlying virtual spaces. rf_show_vslist = (1 << 3), --- old/src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.cpp 2019-12-03 19:36:58.000000000 -0800 +++ new/src/hotspot/share/memory/metaspace/printCLDMetaspaceInfoClosure.cpp 2019-12-03 19:36:58.000000000 -0800 @@ -104,7 +104,7 @@ _out->print(UINTX_FORMAT_W(4) ": ", _num_loaders); // Print "CLD for [,] instance of " - // or "CLD for , loaded by [,] instance of " + // or "CLD for