--- old/src/share/vm/classfile/classLoaderData.cpp 2017-04-14 10:28:59.092144554 -0400 +++ new/src/share/vm/classfile/classLoaderData.cpp 2017-04-14 10:28:57.504144489 -0400 @@ -97,6 +97,21 @@ _next(NULL), _dependencies(dependencies), _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true, Monitor::_safepoint_check_never)) { + + // A ClassLoaderData created solely for an anonymous class should never have a + // ModuleEntryTable or PackageEntryTable created for it. The defining package + // and module for an anonymous class will be found in its host class. + if (!is_anonymous) { + if (h_class_loader.is_null()) { + // Create unnamed module for boot loader + _unnamed_module = ModuleEntry::create_boot_unnamed_module(this); + } else { + // Create unnamed module for all other loaders + _unnamed_module = ModuleEntry::create_unnamed_module(this); + } + } else { + _unnamed_module = NULL; + } TRACE_INIT_ID(this); } @@ -276,6 +291,9 @@ void ClassLoaderData::modules_do(void f(ModuleEntry*)) { assert_locked_or_safepoint(Module_lock); + if (_unnamed_module != NULL) { + f(_unnamed_module); + } if (_modules != NULL) { for (int i = 0; i < _modules->table_size(); i++) { for (ModuleEntry* entry = _modules->bucket(i); @@ -501,10 +519,6 @@ // Check if _modules got allocated while we were waiting for this lock. if ((modules = _modules) == NULL) { modules = new ModuleEntryTable(ModuleEntryTable::_moduletable_entry_size); - // Each loader has one unnamed module entry. Create it before - // any classes, loaded by this loader, are defined in case - // they end up being defined in loader's unnamed module. - modules->create_unnamed_module(this); { MutexLockerEx m1(metaspace_lock(), Mutex::_no_safepoint_check_flag); @@ -529,7 +543,6 @@ return alive; } - ClassLoaderData::~ClassLoaderData() { // Release C heap structures for all the classes. classes_do(InstanceKlass::release_C_heap_structures); @@ -548,6 +561,11 @@ _modules = NULL; } + if (_unnamed_module != NULL) { + FREE_C_HEAP_ARRAY(char, _unnamed_module); + _unnamed_module = NULL; + } + // release the metaspace Metaspace *m = _metaspace; if (m != NULL) { --- old/src/share/vm/classfile/classLoaderData.hpp 2017-04-14 10:29:04.236144767 -0400 +++ new/src/share/vm/classfile/classLoaderData.hpp 2017-04-14 10:29:03.020144717 -0400 @@ -221,6 +221,7 @@ Klass* volatile _klasses; // The classes defined by the class loader. PackageEntryTable* volatile _packages; // The packages defined by the class loader. + ModuleEntry* _unnamed_module; // This class loader's unnamed module. ModuleEntryTable* volatile _modules; // The modules defined by the class loader. // These method IDs are created for the class loader and set to NULL when the @@ -348,6 +349,7 @@ void init_dependencies(TRAPS); PackageEntryTable* packages(); bool packages_defined() { return (_packages != NULL); } + ModuleEntry* unnamed_module() { return _unnamed_module; } ModuleEntryTable* modules(); bool modules_defined() { return (_modules != NULL); } --- old/src/share/vm/classfile/javaClasses.cpp 2017-04-14 10:29:06.544144862 -0400 +++ new/src/share/vm/classfile/javaClasses.cpp 2017-04-14 10:29:06.024144841 -0400 @@ -2863,7 +2863,7 @@ oop loader = java_lang_reflect_Module::loader(module); Handle h_loader = Handle(THREAD, loader); ClassLoaderData* loader_cld = SystemDictionary::register_loader(h_loader, CHECK_NULL); - return loader_cld->modules()->unnamed_module(); + return loader_cld->unnamed_module(); } return module_entry; } --- old/src/share/vm/classfile/moduleEntry.cpp 2017-04-14 10:29:08.684144951 -0400 +++ new/src/share/vm/classfile/moduleEntry.cpp 2017-04-14 10:29:07.596144906 -0400 @@ -129,6 +129,11 @@ // Add a new module to this module's reads list void ModuleEntry::add_read(ModuleEntry* m) { + // Unnamed module is special cased and can read all modules + if (!is_named()) { + return; + } + MutexLocker m1(Module_lock); if (m == NULL) { set_can_read_all_unnamed(); @@ -153,6 +158,7 @@ // safepoint. Modules have the same life cycle as their defining class // loaders and should be removed if dead. void ModuleEntry::set_read_walk_required(ClassLoaderData* m_loader_data) { + assert(is_named(), "Cannot call set_read_walk_required on unnamed module"); assert_locked_or_safepoint(Module_lock); if (!_must_walk_reads && loader_data() != m_loader_data && @@ -166,6 +172,8 @@ } } +// Returns true if the module has a non-empty reads list. As such, the unnamed +// module will return false. bool ModuleEntry::has_reads() const { assert_locked_or_safepoint(Module_lock); return ((_reads != NULL) && !_reads->is_empty()); @@ -219,8 +227,58 @@ _reads = NULL; } +ModuleEntry* ModuleEntry::create_unnamed_module(ClassLoaderData* cld) { + // The java.lang.Module for this loader's + // corresponding unnamed module can be found in the java.lang.ClassLoader object. + oop module = java_lang_ClassLoader::unnamedModule(cld->class_loader()); + ModuleEntry* unnamed_module = new_unnamed_module_entry(Handle(Thread::current(), module), cld); + + // Store pointer to the ModuleEntry in the unnamed module's java.lang.Module + // object. + java_lang_reflect_Module::set_module_entry(module, unnamed_module); + + return unnamed_module; +} + +ModuleEntry* ModuleEntry::create_boot_unnamed_module(ClassLoaderData* cld) { + // For the boot loader, the java.lang.Module for the unnamed module + // is not known until a call to JVM_SetBootLoaderUnnamedModule is made. At + // this point initially create the ModuleEntry for the unnamed module. + ModuleEntry* unnamed_module = new_unnamed_module_entry(Handle(), cld); + assert(unnamed_module != NULL, "boot loader unnamed module should not be null"); + return unnamed_module; +} + +// When creating an unnamed module, this is called without holding the Module_lock. +// This is okay because the unnamed module gets created before the ClassLoaderData +// is available to other threads. +ModuleEntry* ModuleEntry::new_unnamed_module_entry(Handle module_handle, ClassLoaderData* cld) { + ModuleEntry* entry = (ModuleEntry*) NEW_C_HEAP_ARRAY(char, sizeof(ModuleEntry), mtModule); + + // Initialize everything BasicHashtable would + entry->set_next(NULL); + entry->set_hash(0); + entry->set_literal(NULL); + + // Initialize fields specific to a ModuleEntry + entry->init(); + + // Unnamed modules can read all other unnamed modules. + entry->set_can_read_all_unnamed(); + + if (!module_handle.is_null()) { + entry->set_module(cld->add_handle(module_handle)); + } + + entry->set_loader_data(cld); + + TRACE_INIT_ID(entry); + + return entry; +} + ModuleEntryTable::ModuleEntryTable(int table_size) - : Hashtable(table_size, sizeof(ModuleEntry)), _unnamed_module(NULL) + : Hashtable(table_size, sizeof(ModuleEntry)) { } @@ -261,30 +319,6 @@ free_buckets(); } -void ModuleEntryTable::create_unnamed_module(ClassLoaderData* loader_data) { - assert(Module_lock->owned_by_self(), "should have the Module_lock"); - - // Each ModuleEntryTable has exactly one unnamed module - if (loader_data->is_the_null_class_loader_data()) { - // For the boot loader, the java.lang.reflect.Module for the unnamed module - // is not known until a call to JVM_SetBootLoaderUnnamedModule is made. At - // this point initially create the ModuleEntry for the unnamed module. - _unnamed_module = new_entry(0, Handle(), NULL, NULL, NULL, loader_data); - } else { - // For all other class loaders the java.lang.reflect.Module for their - // corresponding unnamed module can be found in the java.lang.ClassLoader object. - oop module = java_lang_ClassLoader::unnamedModule(loader_data->class_loader()); - _unnamed_module = new_entry(0, Handle(Thread::current(), module), NULL, NULL, NULL, loader_data); - - // Store pointer to the ModuleEntry in the unnamed module's java.lang.reflect.Module - // object. - java_lang_reflect_Module::set_module_entry(module, _unnamed_module); - } - - // Add to bucket 0, no name to hash on - add_entry(0, _unnamed_module); -} - ModuleEntry* ModuleEntryTable::new_entry(unsigned int hash, Handle module_handle, Symbol* name, Symbol* version, Symbol* location, ClassLoaderData* loader_data) { @@ -351,10 +385,7 @@ // lookup_only by Symbol* to find a ModuleEntry. ModuleEntry* ModuleEntryTable::lookup_only(Symbol* name) { - if (name == NULL) { - // Return this table's unnamed module - return unnamed_module(); - } + assert(name != NULL, "name cannot be NULL"); int index = index_for(name); for (ModuleEntry* m = bucket(index); m != NULL; m = m->next()) { if (m->name()->fast_compare(name) == 0) { --- old/src/share/vm/classfile/moduleEntry.hpp 2017-04-14 10:29:10.268145016 -0400 +++ new/src/share/vm/classfile/moduleEntry.hpp 2017-04-14 10:29:09.756144995 -0400 @@ -108,7 +108,7 @@ bool is_non_jdk_module(); bool can_read(ModuleEntry* m) const; - bool has_reads() const; + bool has_reads() const; // Whether the module has a non-empty reads list void add_read(ModuleEntry* m); void set_read_walk_required(ClassLoaderData* m_loader_data); @@ -158,6 +158,11 @@ void purge_reads(); void delete_reads(); + // Special handling for unnamed module, one per class loader + static ModuleEntry* create_unnamed_module(ClassLoaderData* cld); + static ModuleEntry* create_boot_unnamed_module(ClassLoaderData* cld); + static ModuleEntry* new_unnamed_module_entry(Handle module_handle, ClassLoaderData* cld); + void print(outputStream* st = tty); void verify(); }; @@ -191,7 +196,6 @@ private: static ModuleEntry* _javabase_module; - ModuleEntry* _unnamed_module; ModuleEntry* new_entry(unsigned int hash, Handle module_handle, Symbol* name, Symbol* version, Symbol* location, ClassLoaderData* loader_data); @@ -228,10 +232,6 @@ // purge dead weak references out of reads list void purge_all_module_reads(); - // Special handling for unnamed module, one per class loader's ModuleEntryTable - void create_unnamed_module(ClassLoaderData* loader_data); - ModuleEntry* unnamed_module() { return _unnamed_module; } - // Special handling for java.base static ModuleEntry* javabase_moduleEntry() { return _javabase_module; } static void set_javabase_moduleEntry(ModuleEntry* java_base) { _javabase_module = java_base; } --- old/src/share/vm/classfile/modules.cpp 2017-04-14 10:29:13.920145167 -0400 +++ new/src/share/vm/classfile/modules.cpp 2017-04-14 10:29:12.780145120 -0400 @@ -89,6 +89,13 @@ return loader_cld->modules(); } +static ModuleEntry* get_unnamed_module(Handle h_loader, TRAPS) { + // This code can be called during start-up, before the classLoader's classLoader data got + // created. So, call register_loader() to make sure the classLoader data gets created. + ClassLoaderData *loader_cld = SystemDictionary::register_loader(h_loader, CHECK_NULL); + return loader_cld->unnamed_module(); +} + static PackageEntryTable* get_package_entry_table(Handle h_loader, TRAPS) { // This code can be called during start-up, before the classLoader's classLoader data got // created. So, call register_loader() to make sure the classLoader data gets created. @@ -478,11 +485,8 @@ log_debug(modules)("set_bootloader_unnamed_module(): recording unnamed module for boot loader"); - // Ensure the boot loader's PackageEntryTable has been created - ModuleEntryTable* module_table = get_module_entry_table(h_loader, CHECK); - - // Set java.lang.reflect.Module for the boot loader's unnamed module - ModuleEntry* unnamed_module = module_table->unnamed_module(); + // Set java.lang.Module for the boot loader's unnamed module + ModuleEntry* unnamed_module = get_unnamed_module(h_loader, CHECK); assert(unnamed_module != NULL, "boot loader's unnamed ModuleEntry not defined"); unnamed_module->set_module(ClassLoaderData::the_null_class_loader_data()->add_handle(module_handle)); // Store pointer to the ModuleEntry in the unnamed module's java.lang.reflect.Module object. --- old/src/share/vm/classfile/packageEntry.hpp 2017-04-14 10:29:19.196145385 -0400 +++ new/src/share/vm/classfile/packageEntry.hpp 2017-04-14 10:29:17.596145319 -0400 @@ -211,7 +211,7 @@ friend class VMStructs; public: enum Constants { - _packagetable_entry_size = 1009 // number of entries in package entry table + _packagetable_entry_size = 109 // number of entries in package entry table }; private: --- old/src/share/vm/classfile/systemDictionary.cpp 2017-04-14 10:29:20.804145451 -0400 +++ new/src/share/vm/classfile/systemDictionary.cpp 2017-04-14 10:29:20.288145430 -0400 @@ -1292,7 +1292,7 @@ pkg_entry == NULL || pkg_entry->in_unnamed_module()) { assert(mod_entry == NULL || - mod_entry == loader_data->modules()->unnamed_module(), + mod_entry == loader_data->unnamed_module(), "the unnamed module is not defined in the classloader"); return true; } --- old/src/share/vm/oops/instanceKlass.cpp 2017-04-14 10:29:23.052145544 -0400 +++ new/src/share/vm/oops/instanceKlass.cpp 2017-04-14 10:29:22.524145522 -0400 @@ -2257,9 +2257,9 @@ } const Klass* host = host_klass(); if (host == NULL) { - return class_loader_data()->modules()->unnamed_module(); + return class_loader_data()->unnamed_module(); } - return host->class_loader_data()->modules()->unnamed_module(); + return host->class_loader_data()->unnamed_module(); } void InstanceKlass::set_package(ClassLoaderData* loader_data, TRAPS) { @@ -2289,9 +2289,9 @@ assert(ModuleEntryTable::javabase_moduleEntry() != NULL, JAVA_BASE_NAME " module is NULL"); _package_entry = loader_data->packages()->lookup(pkg_name, ModuleEntryTable::javabase_moduleEntry()); } else { - assert(loader_data->modules()->unnamed_module() != NULL, "unnamed module is NULL"); + assert(loader_data->unnamed_module() != NULL, "unnamed module is NULL"); _package_entry = loader_data->packages()->lookup(pkg_name, - loader_data->modules()->unnamed_module()); + loader_data->unnamed_module()); } // A package should have been successfully created