diff --git a/src/hotspot/share/cds/cdsHeapVerifier.cpp b/src/hotspot/share/cds/cdsHeapVerifier.cpp index 2f3c2521b22fa..0da9e3f2c8da6 100644 --- a/src/hotspot/share/cds/cdsHeapVerifier.cpp +++ b/src/hotspot/share/cds/cdsHeapVerifier.cpp @@ -110,11 +110,13 @@ CDSHeapVerifier::CDSHeapVerifier() : _archived_objs(0), _problems(0) ADD_EXCL("java/lang/System", "bootLayer"); // A - ADD_EXCL("java/util/Collections", "EMPTY_LIST"); // E + ADD_EXCL("java/util/Collections", "EMPTY_LIST"); // E // A dummy object used by HashSet. The value doesn't matter and it's never // tested for equality. ADD_EXCL("java/util/HashSet", "PRESENT"); // E + + ADD_EXCL("jdk/internal/loader/BootLoader", "UNNAMED_MODULE"); // A ADD_EXCL("jdk/internal/loader/BuiltinClassLoader", "packageToModule"); // A ADD_EXCL("jdk/internal/loader/ClassLoaders", "BOOT_LOADER", // A "APP_LOADER", // A diff --git a/src/hotspot/share/cds/cdsProtectionDomain.cpp b/src/hotspot/share/cds/cdsProtectionDomain.cpp index d509e8afc12d1..e907998fa85cc 100644 --- a/src/hotspot/share/cds/cdsProtectionDomain.cpp +++ b/src/hotspot/share/cds/cdsProtectionDomain.cpp @@ -120,7 +120,6 @@ PackageEntry* CDSProtectionDomain::get_package_entry_from_class(InstanceKlass* i if (CDSConfig::is_using_full_module_graph() && ik->is_shared() && pkg_entry != nullptr) { assert(MetaspaceShared::is_in_shared_metaspace(pkg_entry), "must be"); assert(!ik->defined_by_other_loaders(), "unexpected archived package entry for an unregistered class"); - assert(ik->module()->is_named(), "unexpected archived package entry for a class in an unnamed module"); return pkg_entry; } TempNewSymbol pkg_name = ClassLoader::package_from_class_name(ik->name()); diff --git a/src/hotspot/share/classfile/classLoaderDataShared.cpp b/src/hotspot/share/classfile/classLoaderDataShared.cpp index ac84a24267f35..a495327864da8 100644 --- a/src/hotspot/share/classfile/classLoaderDataShared.cpp +++ b/src/hotspot/share/classfile/classLoaderDataShared.cpp @@ -24,6 +24,7 @@ #include "cds/aotLogging.hpp" #include "cds/cdsConfig.hpp" +#include "cds/heapShared.hpp" #include "cds/serializeClosure.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/classLoaderDataShared.hpp" @@ -42,6 +43,7 @@ bool ClassLoaderDataShared::_full_module_graph_loaded = false; class ArchivedClassLoaderData { Array* _packages; Array* _modules; + ModuleEntry* _unnamed_module; void assert_valid(ClassLoaderData* loader_data) { // loader_data may be null if the boot layer has loaded no modules for the platform or @@ -52,15 +54,19 @@ class ArchivedClassLoaderData { } } public: - ArchivedClassLoaderData() : _packages(nullptr), _modules(nullptr) {} + ArchivedClassLoaderData() : _packages(nullptr), _modules(nullptr), _unnamed_module(nullptr) {} void iterate_symbols(ClassLoaderData* loader_data, MetaspaceClosure* closure); void allocate(ClassLoaderData* loader_data); void init_archived_entries(ClassLoaderData* loader_data); + ModuleEntry* unnamed_module() { + return _unnamed_module; + } void serialize(SerializeClosure* f) { f->do_ptr(&_packages); f->do_ptr(&_modules); + f->do_ptr(&_unnamed_module); } void restore(ClassLoaderData* loader_data, bool do_entries, bool do_oops); @@ -71,6 +77,8 @@ static ArchivedClassLoaderData _archived_boot_loader_data; static ArchivedClassLoaderData _archived_platform_loader_data; static ArchivedClassLoaderData _archived_system_loader_data; static ModuleEntry* _archived_javabase_moduleEntry = nullptr; +static int _platform_loader_root_index = -1; +static int _system_loader_root_index = -1; void ArchivedClassLoaderData::iterate_symbols(ClassLoaderData* loader_data, MetaspaceClosure* closure) { assert(CDSConfig::is_dumping_full_module_graph(), "must be"); @@ -78,6 +86,7 @@ void ArchivedClassLoaderData::iterate_symbols(ClassLoaderData* loader_data, Meta if (loader_data != nullptr) { loader_data->packages()->iterate_symbols(closure); loader_data->modules() ->iterate_symbols(closure); + loader_data->unnamed_module()->iterate_symbols(closure); } } @@ -91,6 +100,7 @@ void ArchivedClassLoaderData::allocate(ClassLoaderData* loader_data) { // the hashtables using these arrays. _packages = loader_data->packages()->allocate_archived_entries(); _modules = loader_data->modules() ->allocate_archived_entries(); + _unnamed_module = loader_data->unnamed_module()->allocate_archived_entry(); } } @@ -100,6 +110,7 @@ void ArchivedClassLoaderData::init_archived_entries(ClassLoaderData* loader_data if (loader_data != nullptr) { loader_data->packages()->init_archived_entries(_packages); loader_data->modules() ->init_archived_entries(_modules); + _unnamed_module->init_as_archived_entry(); } } @@ -117,6 +128,12 @@ void ArchivedClassLoaderData::restore(ClassLoaderData* loader_data, bool do_entr } if (do_oops) { modules->restore_archived_oops(loader_data, _modules); + if (_unnamed_module != nullptr) { + oop module_oop = _unnamed_module->module_oop(); + assert(module_oop != nullptr, "must be already set"); + assert(_unnamed_module == java_lang_Module::module_entry(module_oop), "must be already set"); + assert(loader_data->class_loader() == java_lang_Module::loader(module_oop), "must be set in dump time"); + } } } } @@ -127,6 +144,9 @@ void ArchivedClassLoaderData::clear_archived_oops() { for (int i = 0; i < _modules->length(); i++) { _modules->at(i)->clear_archived_oops(); } + if (_unnamed_module != nullptr) { + _unnamed_module->clear_archived_oops(); + } } } @@ -177,10 +197,15 @@ void ClassLoaderDataShared::allocate_archived_tables() { void ClassLoaderDataShared::init_archived_tables() { assert(CDSConfig::is_dumping_full_module_graph(), "must be"); + _archived_boot_loader_data.init_archived_entries (null_class_loader_data()); _archived_platform_loader_data.init_archived_entries(java_platform_loader_data_or_null()); _archived_system_loader_data.init_archived_entries (java_system_loader_data_or_null()); + _archived_javabase_moduleEntry = ModuleEntry::get_archived_entry(ModuleEntryTable::javabase_moduleEntry()); + + _platform_loader_root_index = HeapShared::append_root(SystemDictionary::java_platform_loader()); + _system_loader_root_index = HeapShared::append_root(SystemDictionary::java_system_loader()); } void ClassLoaderDataShared::serialize(SerializeClosure* f) { @@ -188,21 +213,54 @@ void ClassLoaderDataShared::serialize(SerializeClosure* f) { _archived_platform_loader_data.serialize(f); _archived_system_loader_data.serialize(f); f->do_ptr(&_archived_javabase_moduleEntry); + f->do_int(&_platform_loader_root_index); + f->do_int(&_system_loader_root_index); +} - if (f->reading() && CDSConfig::is_using_full_module_graph()) { - // Must be done before ClassLoader::create_javabase() - _archived_boot_loader_data.restore(null_class_loader_data(), true, false); - ModuleEntryTable::set_javabase_moduleEntry(_archived_javabase_moduleEntry); - aot_log_info(aot)("use_full_module_graph = true; java.base = " INTPTR_FORMAT, - p2i(_archived_javabase_moduleEntry)); +ModuleEntry* ClassLoaderDataShared::archived_boot_unnamed_module() { + if (CDSConfig::is_using_full_module_graph()) { + return _archived_boot_loader_data.unnamed_module(); + } else { + return nullptr; } } +ModuleEntry* ClassLoaderDataShared::archived_unnamed_module(ClassLoaderData* loader_data) { + ModuleEntry* archived_module = nullptr; + + if (!Universe::is_module_initialized() && CDSConfig::is_using_full_module_graph()) { + precond(_platform_loader_root_index >= 0); + precond(_system_loader_root_index >= 0); + + if (loader_data->class_loader() == HeapShared::get_root(_platform_loader_root_index)) { + archived_module = _archived_platform_loader_data.unnamed_module(); + } else if (loader_data->class_loader() == HeapShared::get_root(_system_loader_root_index)) { + archived_module = _archived_system_loader_data.unnamed_module(); + } + } + + return archived_module; +} + + void ClassLoaderDataShared::clear_archived_oops() { assert(!CDSConfig::is_using_full_module_graph(), "must be"); _archived_boot_loader_data.clear_archived_oops(); _archived_platform_loader_data.clear_archived_oops(); _archived_system_loader_data.clear_archived_oops(); + if (_platform_loader_root_index >= 0) { + HeapShared::clear_root(_platform_loader_root_index); + HeapShared::clear_root(_system_loader_root_index); + } +} + +// Must be done before ClassLoader::create_javabase() +void ClassLoaderDataShared::restore_archived_entries_for_null_class_loader_data() { + precond(CDSConfig::is_using_full_module_graph()); + _archived_boot_loader_data.restore(null_class_loader_data(), true, false); + ModuleEntryTable::set_javabase_moduleEntry(_archived_javabase_moduleEntry); + aot_log_info(aot)("use_full_module_graph = true; java.base = " INTPTR_FORMAT, + p2i(_archived_javabase_moduleEntry)); } oop ClassLoaderDataShared::restore_archived_oops_for_null_class_loader_data() { diff --git a/src/hotspot/share/classfile/classLoaderDataShared.hpp b/src/hotspot/share/classfile/classLoaderDataShared.hpp index b802f75103005..4ba1c6c21961c 100644 --- a/src/hotspot/share/classfile/classLoaderDataShared.hpp +++ b/src/hotspot/share/classfile/classLoaderDataShared.hpp @@ -30,6 +30,7 @@ class ClassLoaderData; class MetaspaceClosure; +class ModuleEntry; class SerializeClosure; class ClassLoaderDataShared : AllStatic { @@ -42,9 +43,12 @@ class ClassLoaderDataShared : AllStatic { static void init_archived_tables(); static void serialize(SerializeClosure* f); static void clear_archived_oops(); + static void restore_archived_entries_for_null_class_loader_data(); static oop restore_archived_oops_for_null_class_loader_data(); static void restore_java_platform_loader_from_archive(ClassLoaderData* loader_data); static void restore_java_system_loader_from_archive(ClassLoaderData* loader_data); + static ModuleEntry* archived_boot_unnamed_module(); + static ModuleEntry* archived_unnamed_module(ClassLoaderData* loader_data); static bool is_full_module_graph_loaded() { return _full_module_graph_loaded; } }; diff --git a/src/hotspot/share/classfile/moduleEntry.cpp b/src/hotspot/share/classfile/moduleEntry.cpp index 65d7183dbeaf1..7f9bf09aa5142 100644 --- a/src/hotspot/share/classfile/moduleEntry.cpp +++ b/src/hotspot/share/classfile/moduleEntry.cpp @@ -29,9 +29,11 @@ #include "cds/heapShared.hpp" #include "classfile/classLoader.hpp" #include "classfile/classLoaderData.inline.hpp" +#include "classfile/classLoaderDataShared.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/moduleEntry.hpp" #include "classfile/systemDictionary.hpp" +#include "classfile/systemDictionaryShared.hpp" #include "jni.h" #include "logging/log.hpp" #include "logging/logStream.hpp" @@ -317,6 +319,15 @@ ModuleEntry* ModuleEntry::create_unnamed_module(ClassLoaderData* cld) { // corresponding unnamed module can be found in the java.lang.ClassLoader object. oop module = java_lang_ClassLoader::unnamedModule(cld->class_loader()); +#if INCLUDE_CDS_JAVA_HEAP + ModuleEntry* archived_unnamed_module = ClassLoaderDataShared::archived_unnamed_module(cld); + if (archived_unnamed_module != nullptr) { + archived_unnamed_module->load_from_archive(cld); + archived_unnamed_module->restore_archived_oops(cld); + return archived_unnamed_module; + } +#endif + // Ensure that the unnamed module was correctly set when the class loader was constructed. // Guarantee will cause a recognizable crash if the user code has circumvented calling the ClassLoader constructor. ResourceMark rm; @@ -333,6 +344,16 @@ ModuleEntry* ModuleEntry::create_unnamed_module(ClassLoaderData* cld) { } ModuleEntry* ModuleEntry::create_boot_unnamed_module(ClassLoaderData* cld) { +#if INCLUDE_CDS_JAVA_HEAP + ModuleEntry* archived_unnamed_module = ClassLoaderDataShared::archived_boot_unnamed_module(); + if (archived_unnamed_module != nullptr) { + archived_unnamed_module->load_from_archive(cld); + // It's too early to call archived_unnamed_module->restore_archived_oops(cld). + // We will do it inside Modules::set_bootloader_unnamed_module() + return archived_unnamed_module; + } +#endif + // 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. @@ -345,7 +366,6 @@ ModuleEntry* ModuleEntry::create_boot_unnamed_module(ClassLoaderData* cld) { // 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 = new ModuleEntry(module_handle, /*is_open*/true, /*name*/nullptr, /*version*/ nullptr, /*location*/ nullptr, cld); @@ -395,17 +415,17 @@ static int _num_archived_module_entries = 0; static int _num_inited_module_entries = 0; #endif +bool ModuleEntry::should_be_archived() const { + return SystemDictionaryShared::is_builtin_loader(loader_data()); +} + ModuleEntry* ModuleEntry::allocate_archived_entry() const { - assert(is_named(), "unnamed packages/modules are not archived"); + precond(should_be_archived()); + precond(CDSConfig::is_dumping_full_module_graph()); ModuleEntry* archived_entry = (ModuleEntry*)ArchiveBuilder::rw_region_alloc(sizeof(ModuleEntry)); memcpy((void*)archived_entry, (void*)this, sizeof(ModuleEntry)); - if (CDSConfig::is_dumping_full_module_graph()) { - archived_entry->_archived_module_index = HeapShared::append_root(module_oop()); - } else { - archived_entry->_archived_module_index = -1; - } - + archived_entry->_archived_module_index = HeapShared::append_root(module_oop()); if (_archive_modules_entries == nullptr) { _archive_modules_entries = new (mtClass)ArchivedModuleEntries(); } @@ -489,10 +509,14 @@ void ModuleEntry::init_as_archived_entry() { set_archived_reads(write_growable_array(reads())); _loader_data = nullptr; // re-init at runtime - _shared_path_index = AOTClassLocationConfig::dumptime()->get_module_shared_path_index(_location); if (name() != nullptr) { + _shared_path_index = AOTClassLocationConfig::dumptime()->get_module_shared_path_index(_location); _name = ArchiveBuilder::get_buffered_symbol(_name); ArchivePtrMarker::mark_pointer((address*)&_name); + } else { + // _shared_path_index is used only by SystemDictionary::is_shared_class_visible_impl() + // for checking classes in named modules. + _shared_path_index = -1; } if (_version != nullptr) { _version = ArchiveBuilder::get_buffered_symbol(_version); @@ -741,7 +765,7 @@ void ModuleEntryTable::modules_do(ModuleClosure* closure) { _table.iterate_all(do_f); } -void ModuleEntry::print(outputStream* st) { +void ModuleEntry::print(outputStream* st) const { st->print_cr("entry " PTR_FORMAT " name %s module " PTR_FORMAT " loader %s version %s location %s strict %s", p2i(this), name_as_C_string(), diff --git a/src/hotspot/share/classfile/moduleEntry.hpp b/src/hotspot/share/classfile/moduleEntry.hpp index e66999c3cd9b0..1ae504577e3f3 100644 --- a/src/hotspot/share/classfile/moduleEntry.hpp +++ b/src/hotspot/share/classfile/moduleEntry.hpp @@ -186,10 +186,10 @@ class ModuleEntry : public CHeapObj { static ModuleEntry* new_unnamed_module_entry(Handle module_handle, ClassLoaderData* cld); // Note caller requires ResourceMark - const char* name_as_C_string() { + const char* name_as_C_string() const { return is_named() ? name()->as_C_string() : UNNAMED_MODULE; } - void print(outputStream* st = tty); + void print(outputStream* st = tty) const; void verify(); CDS_ONLY(int shared_path_index() { return _shared_path_index;}) @@ -197,6 +197,7 @@ class ModuleEntry : public CHeapObj { JFR_ONLY(DEFINE_TRACE_ID_METHODS;) #if INCLUDE_CDS_JAVA_HEAP + bool should_be_archived() const; void iterate_symbols(MetaspaceClosure* closure); ModuleEntry* allocate_archived_entry() const; void init_as_archived_entry(); diff --git a/src/hotspot/share/classfile/modules.cpp b/src/hotspot/share/classfile/modules.cpp index 72e56b03a584d..c7b5a72945106 100644 --- a/src/hotspot/share/classfile/modules.cpp +++ b/src/hotspot/share/classfile/modules.cpp @@ -474,6 +474,7 @@ void Modules::define_module(Handle module, jboolean is_open, jstring version, } #if INCLUDE_CDS_JAVA_HEAP +static bool _seen_boot_unnamed_module = false; static bool _seen_platform_unnamed_module = false; static bool _seen_system_unnamed_module = false; @@ -509,24 +510,20 @@ void Modules::check_archived_module_oop(oop orig_module_obj) { // For each named module, we archive both the java.lang.Module oop and the ModuleEntry. assert(orig_module_ent->has_been_archived(), "sanity"); } else { - // We only archive two unnamed module oops (for platform and system loaders). These do NOT have an archived - // ModuleEntry. - // - // At runtime, these oops are fetched from java_lang_ClassLoader::unnamedModule(loader) and - // are initialized in ClassLoaderData::ClassLoaderData() => ModuleEntry::create_unnamed_module(), where - // a new ModuleEntry is allocated. - assert(!loader_data->is_boot_class_loader_data(), "unnamed module for boot loader should be not archived"); - assert(!orig_module_ent->has_been_archived(), "sanity"); - - if (SystemDictionary::is_platform_class_loader(loader_data->class_loader())) { + // We always archive unnamed module oop for boot, platform, and system loaders. + precond(orig_module_ent->should_be_archived()); + precond(orig_module_ent->has_been_archived()); + + if (loader_data->is_boot_class_loader_data()) { + assert(!_seen_boot_unnamed_module, "only once"); + _seen_boot_unnamed_module = true; + } else if (SystemDictionary::is_platform_class_loader(loader_data->class_loader())) { assert(!_seen_platform_unnamed_module, "only once"); _seen_platform_unnamed_module = true; } else if (SystemDictionary::is_system_class_loader(loader_data->class_loader())) { assert(!_seen_system_unnamed_module, "only once"); _seen_system_unnamed_module = true; } else { - // The java.lang.Module oop and ModuleEntry of the unnamed module of the boot loader are - // not in the archived module graph. These are always allocated at runtime. ShouldNotReachHere(); } } @@ -777,9 +774,18 @@ void Modules::set_bootloader_unnamed_module(Handle module, TRAPS) { ClassLoaderData* boot_loader_data = ClassLoaderData::the_null_class_loader_data(); ModuleEntry* unnamed_module = boot_loader_data->unnamed_module(); assert(unnamed_module != nullptr, "boot loader's unnamed ModuleEntry not defined"); - unnamed_module->set_module_handle(boot_loader_data->add_handle(module)); - // Store pointer to the ModuleEntry in the unnamed module's java.lang.Module object. - java_lang_Module::set_module_entry(module(), unnamed_module); + +#if INCLUDE_CDS_JAVA_HEAP + if (CDSConfig::is_using_full_module_graph()) { + precond(unnamed_module == ClassLoaderDataShared::archived_boot_unnamed_module()); + unnamed_module->restore_archived_oops(boot_loader_data); + } else +#endif + { + unnamed_module->set_module_handle(boot_loader_data->add_handle(module)); + // Store pointer to the ModuleEntry in the unnamed module's java.lang.Module object. + java_lang_Module::set_module_entry(module(), unnamed_module); + } } void Modules::add_module_exports(Handle from_module, jstring package_name, Handle to_module, TRAPS) { diff --git a/src/hotspot/share/classfile/packageEntry.cpp b/src/hotspot/share/classfile/packageEntry.cpp index eaa311c4bd386..26af9a4936c1f 100644 --- a/src/hotspot/share/classfile/packageEntry.cpp +++ b/src/hotspot/share/classfile/packageEntry.cpp @@ -30,6 +30,7 @@ #include "classfile/packageEntry.hpp" #include "classfile/vmSymbols.hpp" #include "logging/log.hpp" +#include "logging/logStream.hpp" #include "memory/resourceArea.hpp" #include "oops/array.hpp" #include "oops/symbol.hpp" @@ -218,8 +219,12 @@ typedef ResourceHashtable< AnyObj::C_HEAP> ArchivedPackageEntries; static ArchivedPackageEntries* _archived_packages_entries = nullptr; +bool PackageEntry::should_be_archived() const { + return module()->should_be_archived(); +} + PackageEntry* PackageEntry::allocate_archived_entry() const { - assert(!in_unnamed_module(), "unnamed packages/modules are not archived"); + precond(should_be_archived()); PackageEntry* archived_entry = (PackageEntry*)ArchiveBuilder::rw_region_alloc(sizeof(PackageEntry)); memcpy((void*)archived_entry, (void*)this, sizeof(PackageEntry)); @@ -257,6 +262,12 @@ void PackageEntry::init_as_archived_entry() { ArchivePtrMarker::mark_pointer((address*)&_name); ArchivePtrMarker::mark_pointer((address*)&_module); ArchivePtrMarker::mark_pointer((address*)&_qualified_exports); + + LogStreamHandle(Info, aot, package) st; + if (st.is_enabled()) { + st.print("archived "); + print(&st); + } } void PackageEntry::load_from_archive() { @@ -280,7 +291,7 @@ Array* PackageEntryTable::allocate_archived_entries() { // First count the packages in named modules int n = 0; auto count = [&] (const SymbolHandle& key, PackageEntry*& p) { - if (p->module()->is_named()) { + if (p->should_be_archived()) { n++; } }; @@ -290,9 +301,7 @@ Array* PackageEntryTable::allocate_archived_entries() { // reset n n = 0; auto grab = [&] (const SymbolHandle& key, PackageEntry*& p) { - if (p->module()->is_named()) { - // We don't archive unnamed modules, or packages in unnamed modules. They will be - // created on-demand at runtime as classes in such packages are loaded. + if (p->should_be_archived()) { archived_packages->at_put(n++, p); } }; diff --git a/src/hotspot/share/classfile/packageEntry.hpp b/src/hotspot/share/classfile/packageEntry.hpp index 213f115b2d08f..039c7f21fa63c 100644 --- a/src/hotspot/share/classfile/packageEntry.hpp +++ b/src/hotspot/share/classfile/packageEntry.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -208,6 +208,7 @@ class PackageEntry : public CHeapObj { void print(outputStream* st = tty); #if INCLUDE_CDS_JAVA_HEAP + bool should_be_archived() const; void iterate_symbols(MetaspaceClosure* closure); PackageEntry* allocate_archived_entry() const; void init_as_archived_entry(); diff --git a/src/hotspot/share/logging/logTag.hpp b/src/hotspot/share/logging/logTag.hpp index 9edf81d3f272f..6d0bd117ad91d 100644 --- a/src/hotspot/share/logging/logTag.hpp +++ b/src/hotspot/share/logging/logTag.hpp @@ -149,6 +149,7 @@ class outputStream; LOG_TAG(oopstorage) \ LOG_TAG(os) \ LOG_TAG(owner) \ + LOG_TAG(package) \ LOG_TAG(page) \ LOG_TAG(pagesize) \ LOG_TAG(parser) \ diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp index 100ed9b42dd00..cefe8454fb9e9 100644 --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -29,6 +29,7 @@ #include "cds/metaspaceShared.hpp" #include "classfile/classLoader.hpp" #include "classfile/classLoaderDataGraph.hpp" +#include "classfile/classLoaderDataShared.hpp" #include "classfile/javaClasses.hpp" #include "classfile/stringTable.hpp" #include "classfile/symbolTable.hpp" @@ -897,14 +898,20 @@ jint universe_init() { return JNI_EINVAL; } - ClassLoaderData::init_null_class_loader_data(); - #if INCLUDE_CDS if (CDSConfig::is_using_archive()) { // Read the data structures supporting the shared spaces (shared // system dictionary, symbol table, etc.) MetaspaceShared::initialize_shared_spaces(); } +#endif + + ClassLoaderData::init_null_class_loader_data(); + +#if INCLUDE_CDS + if (CDSConfig::is_using_full_module_graph()) { + ClassLoaderDataShared::restore_archived_entries_for_null_class_loader_data(); + } if (CDSConfig::is_dumping_archive()) { CDSConfig::prepare_for_dumping(); } diff --git a/src/java.base/share/classes/jdk/internal/loader/ArchivedClassLoaders.java b/src/java.base/share/classes/jdk/internal/loader/ArchivedClassLoaders.java index 9fcb8cc5943f9..be3425590fcc9 100644 --- a/src/java.base/share/classes/jdk/internal/loader/ArchivedClassLoaders.java +++ b/src/java.base/share/classes/jdk/internal/loader/ArchivedClassLoaders.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ class ArchivedClassLoaders { private final ClassLoader appLoader; private final ServicesCatalog[] servicesCatalogs; private final Map packageToModule; + private final Module unnamedModuleForBootLoader; private ArchivedClassLoaders() { bootLoader = ClassLoaders.bootLoader(); @@ -52,6 +53,7 @@ private ArchivedClassLoaders() { servicesCatalogs[2] = ServicesCatalog.getServicesCatalog(appLoader); packageToModule = BuiltinClassLoader.packageToModule(); + unnamedModuleForBootLoader = BootLoader.getUnnamedModule(); } ClassLoader bootLoader() { @@ -82,6 +84,10 @@ ServicesCatalog servicesCatalog(ClassLoader loader) { return packageToModule; } + Module unnamedModuleForBootLoader() { + return unnamedModuleForBootLoader; + } + static void archive() { archivedClassLoaders = new ArchivedClassLoaders(); } diff --git a/src/java.base/share/classes/jdk/internal/loader/BootLoader.java b/src/java.base/share/classes/jdk/internal/loader/BootLoader.java index c845146a838de..bc5bd9d4265be 100644 --- a/src/java.base/share/classes/jdk/internal/loader/BootLoader.java +++ b/src/java.base/share/classes/jdk/internal/loader/BootLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,12 @@ private BootLoader() { } static { JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); - UNNAMED_MODULE = jla.defineUnnamedModule(null); + ArchivedClassLoaders archivedClassLoaders = ArchivedClassLoaders.get(); + if (archivedClassLoaders != null) { + UNNAMED_MODULE = archivedClassLoaders.unnamedModuleForBootLoader(); + } else { + UNNAMED_MODULE = jla.defineUnnamedModule(null); + } jla.addEnableNativeAccess(UNNAMED_MODULE); setBootLoaderUnnamedModule0(UNNAMED_MODULE); }