--- /dev/null 2019-11-19 22:05:02.069813242 -0800 +++ new/src/hotspot/share/classfile/classLoaderDataShared.cpp 2020-08-12 15:05:00.121686438 -0700 @@ -0,0 +1,187 @@ + /* + * Copyright (c) 2020, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "classfile/classLoaderData.inline.hpp" +#include "classfile/classLoaderDataShared.hpp" +#include "classfile/moduleEntry.hpp" +#include "classfile/packageEntry.hpp" +#include "logging/log.hpp" +#include "memory/metaspaceShared.hpp" + +class ArchivedClassLoaderData { + Array* _packages; + Array* _modules; + + void assert_valid(ClassLoaderData* loader_data) { + // loader_data may be NULL if the boot layer has loaded no modules for the platform or + // system loaders (e.g., if you create a custom JDK image with only java.base). + if (loader_data != NULL) { + assert(!loader_data->has_class_mirror_holder(), + "loaders for non-strong hidden classes or unsafe anonymous classes not supported"); + } + } +public: + ArchivedClassLoaderData() : _packages(NULL), _modules(NULL) {} + + void allocate(ClassLoaderData* loader_data); + void init_archived_entries(ClassLoaderData* loader_data); + void init_archived_oops(ClassLoaderData* loader_data); + + void serialize(SerializeClosure* f) { + f->do_ptr((void**)&_packages); + f->do_ptr((void**)&_modules); + } + + void restore(ClassLoaderData* loader_data, bool do_entries, bool do_oops); +}; + +static ArchivedClassLoaderData _archived_boot_loader_data; +static ArchivedClassLoaderData _archived_platform_loader_data; +static ArchivedClassLoaderData _archived_system_loader_data; +static ModuleEntry* _archived_javabase_moduleEntry = NULL; + +void ArchivedClassLoaderData::allocate(ClassLoaderData* loader_data) { + assert(DumpSharedSpaces, "must be"); + assert_valid(loader_data); + if (loader_data != NULL) { + // We can't create a hashtable at dump time because the hashcode dependes on the + // address of the Symbols, which may be relocated at run time due to ASLR. + _packages = loader_data->packages()->allocate_archived_entries(); + _modules = loader_data->modules() ->allocate_archived_entries(); + } +} + +void ArchivedClassLoaderData::init_archived_entries(ClassLoaderData* loader_data) { + assert(DumpSharedSpaces, "must be"); + assert_valid(loader_data); + if (loader_data != NULL) { + loader_data->packages()->init_archived_entries(_packages); + loader_data->modules() ->init_archived_entries(_modules); + } +} + +void ArchivedClassLoaderData::init_archived_oops(ClassLoaderData* loader_data) { + assert(DumpSharedSpaces, "must be"); + assert_valid(loader_data); + if (loader_data != NULL) { + loader_data->modules()->init_archived_oops(_modules); + } +} + +void ArchivedClassLoaderData::restore(ClassLoaderData* loader_data, bool do_entries, bool do_oops) { + assert(UseSharedSpaces, "must be"); + assert_valid(loader_data); + if (_modules != NULL) { // Could be NULL if we have archived no modules for platform/system loaders + ModuleEntryTable* modules = loader_data->modules(); + PackageEntryTable* packages = loader_data->packages(); + + MutexLocker m1(Module_lock); + if (do_entries) { + modules->load_archived_entries(loader_data, _modules); + packages->load_archived_entries(_packages); + } + if (do_oops) { + modules->restore_archived_oops(loader_data, _modules); + } + } +} + +// ------------------------------ + +ClassLoaderData* ClassLoaderDataShared::null_class_loader_data() { + ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); + assert(loader_data != NULL, "must be"); + return loader_data; +} + +ClassLoaderData* ClassLoaderDataShared::java_platform_loader_data_or_null() { + return ClassLoaderData::class_loader_data_or_null(SystemDictionary::java_platform_loader()); +} + +ClassLoaderData* ClassLoaderDataShared::java_system_loader_data_or_null() { + return ClassLoaderData::class_loader_data_or_null(SystemDictionary::java_system_loader()); +} + +void ClassLoaderDataShared::allocate_archived_tables() { + assert(DumpSharedSpaces, "must be"); + if (MetaspaceShared::use_full_module_graph()) { + _archived_boot_loader_data.allocate (null_class_loader_data()); + _archived_platform_loader_data.allocate(java_platform_loader_data_or_null()); + _archived_system_loader_data.allocate (java_system_loader_data_or_null()); + } +} + +void ClassLoaderDataShared::init_archived_tables() { + assert(DumpSharedSpaces, "must be"); + if (MetaspaceShared::use_full_module_graph()) { + _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()); + } +} + +void ClassLoaderDataShared::init_archived_oops() { + assert(DumpSharedSpaces, "must be"); + if (MetaspaceShared::use_full_module_graph()) { + _archived_boot_loader_data.init_archived_oops (null_class_loader_data()); + _archived_platform_loader_data.init_archived_oops(java_platform_loader_data_or_null()); + _archived_system_loader_data.init_archived_oops (java_system_loader_data_or_null()); + } +} + +void ClassLoaderDataShared::serialize(class SerializeClosure* f) { + _archived_boot_loader_data.serialize(f); + _archived_platform_loader_data.serialize(f); + _archived_system_loader_data.serialize(f); + f->do_ptr((void**)&_archived_javabase_moduleEntry); + + if (f->reading() && MetaspaceShared::use_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); + log_info(cds)("use_full_module_graph = true; java.base = " INTPTR_FORMAT, + p2i(_archived_javabase_moduleEntry)); + } +} + +void ClassLoaderDataShared::restore_archived_oops_for_null_class_loader_data() { + assert(UseSharedSpaces, "must be"); + if (MetaspaceShared::use_full_module_graph()) { + _archived_boot_loader_data.restore(null_class_loader_data(), false, true); + } +} + +void ClassLoaderDataShared::restore_java_platform_loader_from_archive(ClassLoaderData* loader_data) { + assert(UseSharedSpaces, "must be"); + assert(MetaspaceShared::use_full_module_graph(), "must be"); + _archived_platform_loader_data.restore(loader_data, true, true); +} + +void ClassLoaderDataShared::restore_java_system_loader_from_archive(ClassLoaderData* loader_data) { + assert(UseSharedSpaces, "must be"); + assert(MetaspaceShared::use_full_module_graph(), "must be"); + _archived_system_loader_data.restore(loader_data, true, true); +}