--- old/src/hotspot/share/classfile/classLoaderData.cpp 2020-08-31 08:10:32.562373701 -0700 +++ new/src/hotspot/share/classfile/classLoaderData.cpp 2020-08-31 08:10:32.334365118 -0700 @@ -59,11 +59,9 @@ #include "logging/logStream.hpp" #include "memory/allocation.inline.hpp" #include "memory/metadataFactory.hpp" -#include "memory/iterator.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/access.inline.hpp" -#include "oops/array.hpp" #include "oops/oop.inline.hpp" #include "oops/oopHandle.inline.hpp" #include "oops/weakHandle.inline.hpp" --- old/src/hotspot/share/classfile/classLoaderDataShared.cpp 2020-08-31 08:10:33.194397492 -0700 +++ new/src/hotspot/share/classfile/classLoaderDataShared.cpp 2020-08-31 08:10:32.966388909 -0700 @@ -29,6 +29,9 @@ #include "classfile/packageEntry.hpp" #include "logging/log.hpp" #include "memory/metaspaceShared.hpp" +#include "runtime/handles.inline.hpp" + +#if INCLUDE_CDS_JAVA_HEAP class ArchivedClassLoaderData { Array* _packages; @@ -125,31 +128,25 @@ } 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()); - } + assert(DumpSharedSpaces && MetaspaceShared::use_full_module_graph(), "must be"); + _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()); - } + assert(DumpSharedSpaces && MetaspaceShared::use_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()); } 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()); - } + assert(DumpSharedSpaces && MetaspaceShared::use_full_module_graph(), "must be"); + _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) { @@ -167,21 +164,20 @@ } } -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); - } +oop ClassLoaderDataShared::restore_archived_oops_for_null_class_loader_data() { + assert(UseSharedSpaces && MetaspaceShared::use_full_module_graph(), "must be"); + _archived_boot_loader_data.restore(null_class_loader_data(), false, true); + return _archived_javabase_moduleEntry->module(); } void ClassLoaderDataShared::restore_java_platform_loader_from_archive(ClassLoaderData* loader_data) { - assert(UseSharedSpaces, "must be"); - assert(MetaspaceShared::use_full_module_graph(), "must be"); + assert(UseSharedSpaces && 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"); + assert(UseSharedSpaces && MetaspaceShared::use_full_module_graph(), "must be"); _archived_system_loader_data.restore(loader_data, true, true); } + +#endif // INCLUDE_CDS_JAVA_HEAP --- old/src/hotspot/share/classfile/classLoaderDataShared.hpp 2020-08-31 08:10:33.838421734 -0700 +++ new/src/hotspot/share/classfile/classLoaderDataShared.hpp 2020-08-31 08:10:33.602412850 -0700 @@ -22,7 +22,10 @@ * */ -#if INCLUDE_CDS_JAVA_HEAP +#ifndef SHARE_CLASSFILE_CLASSLOADERDATASHARED_HPP +#define SHARE_CLASSFILE_CLASSLOADERDATASHARED_HPP + +#include "utilities/exceptions.hpp" class SerializeClosure; class ClassLoaderData; @@ -37,9 +40,9 @@ static void init_archived_tables(); static void init_archived_oops(); static void serialize(SerializeClosure* f); - static void restore_archived_oops_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); }; -#endif // INCLUDE_CDS_JAVA_HEAP +#endif // SHARE_CLASSFILE_CLASSLOADERDATASHARED_HPP --- old/src/hotspot/share/classfile/moduleEntry.cpp 2020-08-31 08:10:34.454444922 -0700 +++ new/src/hotspot/share/classfile/moduleEntry.cpp 2020-08-31 08:10:34.234436640 -0700 @@ -487,6 +487,7 @@ } static int compare_module_by_name(ModuleEntry* a, ModuleEntry* b) { + assert(a == b || a->name() != b->name(), "no duplicated names"); return a->name()->fast_compare(b->name()); } --- old/src/hotspot/share/classfile/modules.cpp 2020-08-31 08:10:35.094469014 -0700 +++ new/src/hotspot/share/classfile/modules.cpp 2020-08-31 08:10:34.858460130 -0700 @@ -42,6 +42,7 @@ #include "logging/logStream.hpp" #include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" +#include "prims/jvmtiExport.hpp" #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" #include "runtime/jniHandles.inline.hpp" @@ -270,6 +271,7 @@ void Modules::define_module(jobject module, jboolean is_open, jstring version, jstring location, jobjectArray packages, TRAPS) { + check_cds_restrictions(CHECK); ResourceMark rm(THREAD); if (module == NULL) { @@ -454,6 +456,19 @@ #if INCLUDE_CDS_JAVA_HEAP void Modules::define_archived_modules(jobject platform_loader, jobject system_loader, TRAPS) { + assert(UseSharedSpaces && MetaspaceShared::use_full_module_graph(), "must be"); + + // We don't want the classes used by the archived full module graph to be redefined by JVMTI. + // Luckily, such classes are loaded in the JVMTI "early" phase, and CDS is disable if a JVMTI + // agent wants to redefine classes in this phase. + JVMTI_ONLY(assert(JvmtiExport::is_early_phase(), "must be")); + assert(!(JvmtiExport::should_post_class_file_load_hook() && JvmtiExport::has_early_class_hook_env()), + "CDS should be disabled if early class hooks are enabled"); + + Handle java_base_module(THREAD, ClassLoaderDataShared::restore_archived_oops_for_null_class_loader_data()); + // Patch any previously loaded class's module field with java.base's java.lang.Module. + ModuleEntryTable::patch_javabase_entries(java_base_module); + if (platform_loader == NULL) { THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Null platform loader object"); } @@ -462,14 +477,19 @@ THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Null system loader object"); } - if (UseSharedSpaces && MetaspaceShared::use_full_module_graph()) { - Handle h_platform_loader(THREAD, JNIHandles::resolve_non_null(platform_loader)); - ClassLoaderData* platform_loader_data = SystemDictionary::register_loader(h_platform_loader); - ClassLoaderDataShared::restore_java_platform_loader_from_archive(platform_loader_data); - - Handle h_system_loader(THREAD, JNIHandles::resolve_non_null(system_loader)); - ClassLoaderData* system_loader_data = SystemDictionary::register_loader(h_system_loader); - ClassLoaderDataShared::restore_java_system_loader_from_archive(system_loader_data); + Handle h_platform_loader(THREAD, JNIHandles::resolve_non_null(platform_loader)); + ClassLoaderData* platform_loader_data = SystemDictionary::register_loader(h_platform_loader); + ClassLoaderDataShared::restore_java_platform_loader_from_archive(platform_loader_data); + + Handle h_system_loader(THREAD, JNIHandles::resolve_non_null(system_loader)); + ClassLoaderData* system_loader_data = SystemDictionary::register_loader(h_system_loader); + ClassLoaderDataShared::restore_java_system_loader_from_archive(system_loader_data); +} + +void Modules::check_cds_restrictions(TRAPS) { + if (DumpSharedSpaces && Universe::is_module_initialized() && MetaspaceShared::use_full_module_graph()) { + THROW_MSG(vmSymbols::java_lang_UnsupportedOperationException(), + "During -Xshare:dump, module system cannot be modified after it's initialized"); } } #endif @@ -512,6 +532,7 @@ } void Modules::add_module_exports(jobject from_module, jstring package_name, jobject to_module, TRAPS) { + check_cds_restrictions(CHECK); if (package_name == NULL) { THROW_MSG(vmSymbols::java_lang_NullPointerException(), @@ -579,6 +600,7 @@ void Modules::add_module_exports_qualified(jobject from_module, jstring package, jobject to_module, TRAPS) { + check_cds_restrictions(CHECK); if (to_module == NULL) { THROW_MSG(vmSymbols::java_lang_NullPointerException(), "to_module is null"); @@ -587,6 +609,7 @@ } void Modules::add_reads_module(jobject from_module, jobject to_module, TRAPS) { + check_cds_restrictions(CHECK); if (from_module == NULL) { THROW_MSG(vmSymbols::java_lang_NullPointerException(), "from_module is null"); @@ -692,6 +715,7 @@ // Export package in module to all unnamed modules. void Modules::add_module_exports_to_all_unnamed(jobject module, jstring package_name, TRAPS) { + check_cds_restrictions(CHECK); if (module == NULL) { THROW_MSG(vmSymbols::java_lang_NullPointerException(), "module is null"); --- old/src/hotspot/share/classfile/modules.hpp 2020-08-31 08:10:35.722492654 -0700 +++ new/src/hotspot/share/classfile/modules.hpp 2020-08-31 08:10:35.494484071 -0700 @@ -32,6 +32,7 @@ class Symbol; class Modules : AllStatic { + static void check_cds_restrictions(TRAPS) NOT_CDS_JAVA_HEAP_RETURN; public: // define_module defines a module containing the specified packages. It binds the --- old/src/hotspot/share/classfile/packageEntry.cpp 2020-08-31 08:10:36.338515842 -0700 +++ new/src/hotspot/share/classfile/packageEntry.cpp 2020-08-31 08:10:36.114507410 -0700 @@ -245,6 +245,7 @@ } static int compare_package_by_name(PackageEntry* a, PackageEntry* b) { + assert(a == b || a->name() != b->name(), "no duplicated names"); return a->name()->fast_compare(b->name()); } --- old/src/hotspot/share/classfile/systemDictionary.cpp 2020-08-31 08:10:36.966539482 -0700 +++ new/src/hotspot/share/classfile/systemDictionary.cpp 2020-08-31 08:10:36.738530899 -0700 @@ -30,7 +30,6 @@ #include "classfile/classLoader.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/classLoaderDataGraph.inline.hpp" -#include "classfile/classLoaderDataShared.hpp" #include "classfile/classLoaderExt.hpp" #include "classfile/dictionary.hpp" #include "classfile/javaClasses.inline.hpp" @@ -2113,7 +2112,6 @@ // call. No mirror objects are accessed/restored in the above call. // Mirrors are restored after java.lang.Class is loaded. HeapShared::fixup_mapped_heap_regions(); - CDS_JAVA_HEAP_ONLY(ClassLoaderDataShared::restore_archived_oops_for_null_class_loader_data()); // Initialize the constant pool for the Object_class assert(Object_klass()->is_shared(), "must be"); --- old/src/hotspot/share/memory/heapShared.cpp 2020-08-31 08:10:37.622564176 -0700 +++ new/src/hotspot/share/memory/heapShared.cpp 2020-08-31 08:10:37.398555744 -0700 @@ -277,7 +277,9 @@ log_info(cds)("Dumping objects to open archive heap region ..."); copy_open_archive_heap_objects(open); - ClassLoaderDataShared::init_archived_oops(); + if (MetaspaceShared::use_full_module_graph()) { + ClassLoaderDataShared::init_archived_oops(); + } destroy_archived_object_cache(); } --- old/src/hotspot/share/memory/metaspaceShared.cpp 2020-08-31 08:10:38.258588117 -0700 +++ new/src/hotspot/share/memory/metaspaceShared.cpp 2020-08-31 08:10:38.030579535 -0700 @@ -1076,19 +1076,23 @@ _mc_region.pack(&_rw_region); builder.dump_rw_region(); #if INCLUDE_CDS_JAVA_HEAP - // Archive the ModuleEntry's and PackageEntry's of the 3 built-in loaders - char* start = _rw_region.top(); - ClassLoaderDataShared::allocate_archived_tables(); - ArchiveBuilder::alloc_stats()->record_modules(_rw_region.top() - start, /*read_only*/false); + if (MetaspaceShared::use_full_module_graph()) { + // Archive the ModuleEntry's and PackageEntry's of the 3 built-in loaders + char* start = _rw_region.top(); + ClassLoaderDataShared::allocate_archived_tables(); + ArchiveBuilder::alloc_stats()->record_modules(_rw_region.top() - start, /*read_only*/false); + } #endif } { _rw_region.pack(&_ro_region); builder.dump_ro_region(); #if INCLUDE_CDS_JAVA_HEAP - char* start = _ro_region.top(); - ClassLoaderDataShared::init_archived_tables(); - ArchiveBuilder::alloc_stats()->record_modules(_ro_region.top() - start, /*read_only*/true); + if (MetaspaceShared::use_full_module_graph()) { + char* start = _ro_region.top(); + ClassLoaderDataShared::init_archived_tables(); + ArchiveBuilder::alloc_stats()->record_modules(_ro_region.top() - start, /*read_only*/true); + } #endif } builder.relocate_pointers(); @@ -2060,8 +2064,14 @@ } bool MetaspaceShared::use_full_module_graph() { - return _use_optimized_module_handling && _use_full_module_graph && + bool result = _use_optimized_module_handling && _use_full_module_graph && (UseSharedSpaces || DumpSharedSpaces) && HeapShared::is_heap_object_archiving_allowed(); + if (result && UseSharedSpaces) { + // Classes used by the archived full module graph are loaded in JVMTI early phase. + assert(!(JvmtiExport::should_post_class_file_load_hook() && JvmtiExport::has_early_class_hook_env()), + "CDS should be disabled if early class hooks are enabled"); + } + return result; } void MetaspaceShared::print_on(outputStream* st) { --- old/src/hotspot/share/runtime/arguments.cpp 2020-08-31 08:10:38.902612359 -0700 +++ new/src/hotspot/share/runtime/arguments.cpp 2020-08-31 08:10:38.678603927 -0700 @@ -2514,7 +2514,7 @@ Arguments::append_sysclasspath(tail); #if INCLUDE_CDS MetaspaceShared::disable_optimized_module_handling(); - log_info(cds)("optimized module handling: disabled due to bootclasspath was appended"); + log_info(cds)("optimized module handling: disabled because bootclasspath was appended"); #endif // -bootclasspath/p: } else if (match_option(option, "-Xbootclasspath/p:", &tail)) { --- old/test/hotspot/jtreg/runtime/cds/ServiceLoaderTest.java 2020-08-31 08:10:39.550636752 -0700 +++ new/test/hotspot/jtreg/runtime/cds/ServiceLoaderTest.java 2020-08-31 08:10:39.330628470 -0700 @@ -101,13 +101,13 @@ System.out.println("Testing : " + c.getName()); System.out.println("============================================================"); - dump("default", ServiceLoader.load(c)); - dump("null loader", ServiceLoader.load(c, null)); - dump("platform loader", ServiceLoader.load(c, ServiceLoaderApp.class.getClassLoader().getParent())); - dump("system loader", ServiceLoader.load(c, ServiceLoaderApp.class.getClassLoader())); + print_loader("default", ServiceLoader.load(c)); + print_loader("null loader", ServiceLoader.load(c, null)); + print_loader("platform loader", ServiceLoader.load(c, ServiceLoaderApp.class.getClassLoader().getParent())); + print_loader("system loader", ServiceLoader.load(c, ServiceLoaderApp.class.getClassLoader())); } - static void dump(String testCase, ServiceLoader loader) throws Exception { + static void print_loader(String testCase, ServiceLoader loader) throws Exception { System.out.println("[TEST CASE] " + testCase); System.out.println("[svcloader] " + asString(loader)); Iterator it = loader.iterator(); --- old/test/hotspot/jtreg/runtime/cds/serviceability/ReplaceCriticalClasses.java 2020-08-31 08:10:40.186660693 -0700 +++ new/test/hotspot/jtreg/runtime/cds/serviceability/ReplaceCriticalClasses.java 2020-08-31 08:10:39.958652110 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -53,7 +53,8 @@ .setXShareMode("dump") .setArchiveName(ReplaceCriticalClasses.class.getName() + ".jsa") .setUseVersion(false) - .addSuffix("-showversion"); + .addSuffix("-showversion") + .addSuffix("-Xlog:cds"); CDSTestUtils.run(opts).assertNormalExit(""); launchChildProcesses(getTests()); @@ -80,6 +81,8 @@ "-early -notshared java/lang/String", "-early -notshared java/lang/Cloneable", "-early -notshared java/io/Serializable", + "-early -notshared java/lang/Module", + "-early -notshared java/lang/ModuleLayer", // CDS should not be disabled -- these critical classes cannot be replaced because // JvmtiExport::early_class_hook_env() is false. @@ -87,13 +90,8 @@ "java/lang/String", "java/lang/Cloneable", "java/io/Serializable", - - /* Try to replace classes that are used by the archived subgraph graphs. - The following test cases are in ReplaceCriticalClassesForSubgraphs.java. - "-early -notshared -subgraph java/lang/module/ResolvedModule jdk.internal.module.ArchivedModuleGraph", - "-early -notshared -subgraph java/lang/Long java.lang.Long$LongCache", - "-subgraph java/lang/Long java.lang.Long$LongCache", - */ + "java/lang/Module", + "java/lang/ModuleLayer", // Replace classes that are loaded after JVMTI_PHASE_PRIMORDIAL. It's OK to replace // such @@ -116,12 +114,13 @@ static void launchChild(String args[]) throws Throwable { if (args.length < 1) { - throw new RuntimeException("Invalid test case. Should be <-early> <-subgraph> <-notshared> klassName subgraphKlass"); + throw new RuntimeException("Invalid test case. Should be <-early> <-subgraph> <-notshared> <-nowhitebox> klassName subgraphKlass"); } String klassName = null; String subgraphKlass = null; String early = ""; boolean subgraph = false; + boolean whitebox = true; String shared = "-shared"; for (int i=0; i classBeingRedefined, + ProtectionDomain pd, byte[] buffer) throws IllegalClassFormatException { + System.out.println("transforming " + name); + + if (name.equals("java/lang/Module") || + name.equals("java/lang/ModuleLayer") || + name.equals("java/lang/module/ResolvedModule")) { + throw new RuntimeException("Classes used by the module graph should never be transformed by Java agent"); + } + return null; + } +}