8360555: Archive all unnamed modules in CDS full module graph

Reviewed-by: coleenp, vlivanov
This commit is contained in:
Ioi Lam 2025-07-22 20:17:31 +00:00
parent ea6674fec8
commit aae9902234
13 changed files with 169 additions and 46 deletions

View File

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

View File

@ -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());

View File

@ -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<PackageEntry*>* _packages;
Array<ModuleEntry*>* _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() {

View File

@ -30,6 +30,7 @@
class ClassLoaderData;
class MetaspaceClosure;
class ModuleEntry;
class SerializeClosure;
class ClassLoaderDataShared : AllStatic {
@ -42,9 +43,12 @@ public:
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; }
};

View File

@ -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(),

View File

@ -186,10 +186,10 @@ public:
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 @@ public:
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();

View File

@ -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");
// 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 (SystemDictionary::is_platform_class_loader(loader_data->class_loader())) {
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) {

View File

@ -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<PackageEntry*>* 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<PackageEntry*>* 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);
}
};

View File

@ -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 @@ public:
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();

View File

@ -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) \

View File

@ -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();
}

View File

@ -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<String, ?> packageToModule;
private final Module unnamedModuleForBootLoader;
private ArchivedClassLoaders() {
bootLoader = ClassLoaders.bootLoader();
@ -52,6 +53,7 @@ class ArchivedClassLoaders {
servicesCatalogs[2] = ServicesCatalog.getServicesCatalog(appLoader);
packageToModule = BuiltinClassLoader.packageToModule();
unnamedModuleForBootLoader = BootLoader.getUnnamedModule();
}
ClassLoader bootLoader() {
@ -82,6 +84,10 @@ class ArchivedClassLoaders {
return packageToModule;
}
Module unnamedModuleForBootLoader() {
return unnamedModuleForBootLoader;
}
static void archive() {
archivedClassLoaders = new ArchivedClassLoaders();
}

View File

@ -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 @@ public class 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);
}