diff --git a/src/hotspot/share/cds/cdsConfig.cpp b/src/hotspot/share/cds/cdsConfig.cpp index 47613e09008..64ad07b0cf8 100644 --- a/src/hotspot/share/cds/cdsConfig.cpp +++ b/src/hotspot/share/cds/cdsConfig.cpp @@ -51,9 +51,10 @@ bool CDSConfig::_old_cds_flags_used = false; bool CDSConfig::_new_aot_flags_used = false; bool CDSConfig::_disable_heap_dumping = false; -char* CDSConfig::_default_archive_path = nullptr; -char* CDSConfig::_static_archive_path = nullptr; -char* CDSConfig::_dynamic_archive_path = nullptr; +const char* CDSConfig::_default_archive_path = nullptr; +const char* CDSConfig::_input_static_archive_path = nullptr; +const char* CDSConfig::_input_dynamic_archive_path = nullptr; +const char* CDSConfig::_output_archive_path = nullptr; JavaThread* CDSConfig::_dumper_thread = nullptr; @@ -66,7 +67,11 @@ int CDSConfig::get_status() { (is_using_archive() ? IS_USING_ARCHIVE : 0); } -void CDSConfig::initialize() { +DEBUG_ONLY(static bool _cds_ergo_initialize_started = false); + +void CDSConfig::ergo_initialize() { + DEBUG_ONLY(_cds_ergo_initialize_started = true); + if (is_dumping_static_archive() && !is_dumping_final_static_archive()) { // Note: -Xshare and -XX:AOTMode flags are mutually exclusive. // - Classic workflow: -Xshare:on and -Xshare:dump cannot take effect at the same time. @@ -83,10 +88,12 @@ void CDSConfig::initialize() { // Initialize shared archive paths which could include both base and dynamic archive paths // This must be after set_ergonomics_flags() called so flag UseCompressedOops is set properly. - // - // UseSharedSpaces may be disabled if -XX:SharedArchiveFile is invalid. if (is_dumping_static_archive() || is_using_archive()) { - init_shared_archive_paths(); + if (new_aot_flags_used()) { + ergo_init_aot_paths(); + } else { + ergo_init_classic_archive_paths(); + } } if (!is_dumping_heap()) { @@ -94,7 +101,10 @@ void CDSConfig::initialize() { } } -char* CDSConfig::default_archive_path() { +const char* CDSConfig::default_archive_path() { + // The path depends on UseCompressedOops, etc, which are set by GC ergonomics just + // before CDSConfig::ergo_initialize() is called. + assert(_cds_ergo_initialize_started, "sanity"); if (_default_archive_path == nullptr) { stringStream tmp; const char* subdir = WINDOWS_ONLY("bin") NOT_WINDOWS("lib"); @@ -116,12 +126,12 @@ char* CDSConfig::default_archive_path() { return _default_archive_path; } -int CDSConfig::num_archives(const char* archive_path) { - if (archive_path == nullptr) { +int CDSConfig::num_archive_paths(const char* path_spec) { + if (path_spec == nullptr) { return 0; } int npaths = 1; - char* p = (char*)archive_path; + char* p = (char*)path_spec; while (*p != '\0') { if (*p == os::path_separator()[0]) { npaths++; @@ -131,9 +141,9 @@ int CDSConfig::num_archives(const char* archive_path) { return npaths; } -void CDSConfig::extract_shared_archive_paths(const char* archive_path, - char** base_archive_path, - char** top_archive_path) { +void CDSConfig::extract_archive_paths(const char* archive_path, + const char** base_archive_path, + const char** top_archive_path) { char* begin_ptr = (char*)archive_path; char* end_ptr = strchr((char*)archive_path, os::path_separator()[0]); if (end_ptr == nullptr || end_ptr == begin_ptr) { @@ -157,7 +167,8 @@ void CDSConfig::extract_shared_archive_paths(const char* archive_path, *top_archive_path = cur_path; } -void CDSConfig::init_shared_archive_paths() { +void CDSConfig::ergo_init_classic_archive_paths() { + assert(_cds_ergo_initialize_started, "sanity"); if (ArchiveClassesAtExit != nullptr) { assert(!RecordDynamicDumpInfo, "already checked"); if (is_dumping_static_archive()) { @@ -172,21 +183,24 @@ void CDSConfig::init_shared_archive_paths() { } if (SharedArchiveFile == nullptr) { - _static_archive_path = default_archive_path(); + _input_static_archive_path = default_archive_path(); + if (is_dumping_static_archive()) { + _output_archive_path = _input_static_archive_path; + } } else { - int archives = num_archives(SharedArchiveFile); - assert(archives > 0, "must be"); + int num_archives = num_archive_paths(SharedArchiveFile); + assert(num_archives > 0, "must be"); - if (is_dumping_archive() && archives > 1) { + if (is_dumping_archive() && num_archives > 1) { vm_exit_during_initialization( "Cannot have more than 1 archive file specified in -XX:SharedArchiveFile during CDS dumping"); } if (is_dumping_static_archive()) { - assert(archives == 1, "must be"); + assert(num_archives == 1, "just checked above"); // Static dump is simple: only one archive is allowed in SharedArchiveFile. This file - // will be overwritten no matter regardless of its contents - _static_archive_path = os::strdup_check_oom(SharedArchiveFile, mtArguments); + // will be overwritten regardless of its contents + _output_archive_path = SharedArchiveFile; } else { // SharedArchiveFile may specify one or two files. In case (c), the path for base.jsa // is read from top.jsa @@ -197,48 +211,49 @@ void CDSConfig::init_shared_archive_paths() { // However, if either RecordDynamicDumpInfo or ArchiveClassesAtExit is used, we do not // allow cases (b) and (c). Case (b) is already checked above. - if (archives > 2) { + if (num_archives > 2) { vm_exit_during_initialization( "Cannot have more than 2 archive files specified in the -XX:SharedArchiveFile option"); } - if (archives == 1) { - char* base_archive_path = nullptr; + + if (num_archives == 1) { + const char* base_archive_path = nullptr; bool success = FileMapInfo::get_base_archive_name_from_header(SharedArchiveFile, &base_archive_path); if (!success) { // If +AutoCreateSharedArchive and the specified shared archive does not exist, // regenerate the dynamic archive base on default archive. if (AutoCreateSharedArchive && !os::file_exists(SharedArchiveFile)) { - enable_dumping_dynamic_archive(); - ArchiveClassesAtExit = const_cast(SharedArchiveFile); - _static_archive_path = default_archive_path(); - SharedArchiveFile = nullptr; - } else { + enable_dumping_dynamic_archive(SharedArchiveFile); + FLAG_SET_ERGO(ArchiveClassesAtExit, SharedArchiveFile); + _input_static_archive_path = default_archive_path(); + FLAG_SET_ERGO(SharedArchiveFile, nullptr); + } else { if (AutoCreateSharedArchive) { warning("-XX:+AutoCreateSharedArchive is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info."); AutoCreateSharedArchive = false; } - log_error(cds)("Not a valid %s (%s)", new_aot_flags_used() ? "AOT cache" : "archive", SharedArchiveFile); + log_error(cds)("Not a valid archive (%s)", SharedArchiveFile); Arguments::no_shared_spaces("invalid archive"); } } else if (base_archive_path == nullptr) { // User has specified a single archive, which is a static archive. - _static_archive_path = const_cast(SharedArchiveFile); + _input_static_archive_path = SharedArchiveFile; } else { // User has specified a single archive, which is a dynamic archive. - _dynamic_archive_path = const_cast(SharedArchiveFile); - _static_archive_path = base_archive_path; // has been c-heap allocated. + _input_dynamic_archive_path = SharedArchiveFile; + _input_static_archive_path = base_archive_path; // has been c-heap allocated. } } else { - extract_shared_archive_paths((const char*)SharedArchiveFile, - &_static_archive_path, &_dynamic_archive_path); - if (_static_archive_path == nullptr) { - assert(_dynamic_archive_path == nullptr, "must be"); + extract_archive_paths(SharedArchiveFile, + &_input_static_archive_path, &_input_dynamic_archive_path); + if (_input_static_archive_path == nullptr) { + assert(_input_dynamic_archive_path == nullptr, "must be"); Arguments::no_shared_spaces("invalid archive"); } } - if (_dynamic_archive_path != nullptr) { + if (_input_dynamic_archive_path != nullptr) { // Check for case (c) if (RecordDynamicDumpInfo) { vm_exit_during_initialization("-XX:+RecordDynamicDumpInfo is unsupported when a dynamic CDS archive is specified in -XX:SharedArchiveFile", @@ -353,14 +368,22 @@ bool CDSConfig::has_unsupported_runtime_module_options() { return false; } -#define CHECK_ALIAS(f) check_flag_alias(FLAG_IS_DEFAULT(f), #f) +#define CHECK_NEW_FLAG(f) check_new_flag(FLAG_IS_DEFAULT(f), #f) -void CDSConfig::check_flag_alias(bool alias_is_default, const char* alias_name) { - if (old_cds_flags_used() && !alias_is_default) { +void CDSConfig::check_new_flag(bool new_flag_is_default, const char* new_flag_name) { + if (old_cds_flags_used() && !new_flag_is_default) { vm_exit_during_initialization(err_msg("Option %s cannot be used at the same time with " "-Xshare:on, -Xshare:auto, -Xshare:off, -Xshare:dump, " "DumpLoadedClassList, SharedClassListFile, or SharedArchiveFile", - alias_name)); + new_flag_name)); + } +} + +#define CHECK_SINGLE_PATH(f) check_flag_single_path(#f, f) + +void CDSConfig::check_flag_single_path(const char* flag_name, const char* value) { + if (value != nullptr && num_archive_paths(value) != 1) { + vm_exit_during_initialization(err_msg("Option %s must specify a single file name", flag_name)); } } @@ -371,9 +394,13 @@ void CDSConfig::check_aot_flags() { _old_cds_flags_used = true; } - CHECK_ALIAS(AOTCache); - CHECK_ALIAS(AOTConfiguration); - CHECK_ALIAS(AOTMode); + // "New" AOT flags must not be mixed with "classic" flags such as -Xshare:dump + CHECK_NEW_FLAG(AOTCache); + CHECK_NEW_FLAG(AOTConfiguration); + CHECK_NEW_FLAG(AOTMode); + + CHECK_SINGLE_PATH(AOTCache); + CHECK_SINGLE_PATH(AOTConfiguration); if (FLAG_IS_DEFAULT(AOTCache) && FLAG_IS_DEFAULT(AOTConfiguration) && FLAG_IS_DEFAULT(AOTMode)) { // AOTCache/AOTConfiguration/AOTMode not used. @@ -411,11 +438,6 @@ void CDSConfig::check_aotmode_auto_or_on() { vm_exit_during_initialization("AOTConfiguration can only be used with -XX:AOTMode=record or -XX:AOTMode=create"); } - if (!FLAG_IS_DEFAULT(AOTCache)) { - assert(FLAG_IS_DEFAULT(SharedArchiveFile), "already checked"); - FLAG_SET_ERGO(SharedArchiveFile, AOTCache); - } - UseSharedSpaces = true; if (FLAG_IS_DEFAULT(AOTMode) || (strcmp(AOTMode, "auto") == 0)) { RequireSharedSpaces = false; @@ -430,10 +452,6 @@ void CDSConfig::check_aotmode_record() { vm_exit_during_initialization("AOTCache must not be specified when using -XX:AOTMode=record"); } - assert(FLAG_IS_DEFAULT(DumpLoadedClassList), "already checked"); - assert(FLAG_IS_DEFAULT(SharedArchiveFile), "already checked"); - FLAG_SET_ERGO(SharedArchiveFile, AOTConfiguration); - FLAG_SET_ERGO(DumpLoadedClassList, nullptr); UseSharedSpaces = false; RequireSharedSpaces = false; _is_dumping_static_archive = true; @@ -449,10 +467,7 @@ void CDSConfig::check_aotmode_create() { vm_exit_during_initialization("AOTCache must be specified when using -XX:AOTMode=create"); } - assert(FLAG_IS_DEFAULT(SharedArchiveFile), "already checked"); - _is_dumping_final_static_archive = true; - FLAG_SET_ERGO(SharedArchiveFile, AOTConfiguration); UseSharedSpaces = true; RequireSharedSpaces = true; @@ -463,7 +478,29 @@ void CDSConfig::check_aotmode_create() { CDSConfig::enable_dumping_static_archive(); } +void CDSConfig::ergo_init_aot_paths() { + assert(_cds_ergo_initialize_started, "sanity"); + if (is_dumping_static_archive()) { + if (is_dumping_preimage_static_archive()) { + _output_archive_path = AOTConfiguration; + } else { + assert(is_dumping_final_static_archive(), "must be"); + _input_static_archive_path = AOTConfiguration; + _output_archive_path = AOTCache; + } + } else if (is_using_archive()) { + if (FLAG_IS_DEFAULT(AOTCache)) { + // Only -XX:AOTMode={auto,on} is specified + _input_static_archive_path = default_archive_path(); + } else { + _input_static_archive_path = AOTCache; + } + } +} + bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_flag_cmd_line) { + assert(!_cds_ergo_initialize_started, "This is called earlier than CDSConfig::ergo_initialize()"); + check_aot_flags(); if (!FLAG_IS_DEFAULT(AOTMode)) { @@ -514,7 +551,7 @@ bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_fla if (ArchiveClassesAtExit == nullptr && !RecordDynamicDumpInfo) { disable_dumping_dynamic_archive(); } else { - enable_dumping_dynamic_archive(); + enable_dumping_dynamic_archive(ArchiveClassesAtExit); } if (AutoCreateSharedArchive) { @@ -546,6 +583,34 @@ bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_fla return true; } +void CDSConfig::prepare_for_dumping() { + assert(CDSConfig::is_dumping_archive(), "sanity"); + + if (is_dumping_dynamic_archive() && !is_using_archive()) { + assert(!is_dumping_static_archive(), "cannot be dumping both static and dynamic archives"); + + // This could happen if SharedArchiveFile has failed to load: + // - -Xshare:off was specified + // - SharedArchiveFile points to an non-existent file. + // - SharedArchiveFile points to an archive that has failed CRC check + // - SharedArchiveFile is not specified and the VM doesn't have a compatible default archive + +#define __THEMSG " is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info." + if (RecordDynamicDumpInfo) { + log_error(cds)("-XX:+RecordDynamicDumpInfo%s", __THEMSG); + MetaspaceShared::unrecoverable_loading_error(); + } else { + assert(ArchiveClassesAtExit != nullptr, "sanity"); + log_warning(cds)("-XX:ArchiveClassesAtExit" __THEMSG); + } +#undef __THEMSG + disable_dumping_dynamic_archive(); + return; + } + + check_unsupported_dumping_module_options(); +} + bool CDSConfig::is_dumping_classic_static_archive() { return _is_dumping_static_archive && !is_dumping_preimage_static_archive() && @@ -560,6 +625,18 @@ bool CDSConfig::is_dumping_final_static_archive() { return _is_dumping_final_static_archive; } +void CDSConfig::enable_dumping_dynamic_archive(const char* output_path) { + _is_dumping_dynamic_archive = true; + if (output_path == nullptr) { + // output_path can be null when the VM is started with -XX:+RecordDynamicDumpInfo + // in anticipation of "jcmd VM.cds dynamic_dump", which will provide the actual + // output path. + _output_archive_path = nullptr; + } else { + _output_archive_path = os::strdup_check_oom(output_path, mtArguments); + } +} + bool CDSConfig::allow_only_single_java_thread() { // See comments in JVM_StartThread() return is_dumping_classic_static_archive() || is_dumping_final_static_archive(); diff --git a/src/hotspot/share/cds/cdsConfig.hpp b/src/hotspot/share/cds/cdsConfig.hpp index f02258eb6fe..e96291f6534 100644 --- a/src/hotspot/share/cds/cdsConfig.hpp +++ b/src/hotspot/share/cds/cdsConfig.hpp @@ -42,9 +42,10 @@ class CDSConfig : public AllStatic { static bool _is_using_full_module_graph; static bool _has_aot_linked_classes; - static char* _default_archive_path; - static char* _static_archive_path; - static char* _dynamic_archive_path; + const static char* _default_archive_path; + const static char* _input_static_archive_path; + const static char* _input_dynamic_archive_path; + const static char* _output_archive_path; static bool _old_cds_flags_used; static bool _new_aot_flags_used; @@ -53,17 +54,24 @@ class CDSConfig : public AllStatic { static JavaThread* _dumper_thread; #endif - static void extract_shared_archive_paths(const char* archive_path, - char** base_archive_path, - char** top_archive_path); - static void init_shared_archive_paths(); + static void extract_archive_paths(const char* archive_path, + const char** base_archive_path, + const char** top_archive_path); + static int num_archive_paths(const char* path_spec); + static void check_flag_single_path(const char* flag_name, const char* value); - static void check_flag_alias(bool alias_is_default, const char* alias_name); + // Checks before Arguments::apply_ergo() + static void check_new_flag(bool new_flag_is_default, const char* new_flag_name); static void check_aot_flags(); static void check_aotmode_off(); static void check_aotmode_auto_or_on(); static void check_aotmode_record(); static void check_aotmode_create(); + static void check_unsupported_dumping_module_options(); + + // Called after Arguments::apply_ergo() has started + static void ergo_init_classic_archive_paths(); + static void ergo_init_aot_paths(); public: // Used by jdk.internal.misc.CDS.getCDSConfigStatus(); @@ -76,24 +84,25 @@ public: static int get_status() NOT_CDS_RETURN_(0); // Initialization and command-line checking - static void initialize() NOT_CDS_RETURN; + static void ergo_initialize() NOT_CDS_RETURN; static void set_old_cds_flags_used() { CDS_ONLY(_old_cds_flags_used = true); } static bool old_cds_flags_used() { return CDS_ONLY(_old_cds_flags_used) NOT_CDS(false); } static bool new_aot_flags_used() { return CDS_ONLY(_new_aot_flags_used) NOT_CDS(false); } static void check_internal_module_property(const char* key, const char* value) NOT_CDS_RETURN; static void check_incompatible_property(const char* key, const char* value) NOT_CDS_RETURN; - static void check_unsupported_dumping_module_options() NOT_CDS_RETURN; static bool has_unsupported_runtime_module_options() NOT_CDS_RETURN_(false); static bool check_vm_args_consistency(bool patch_mod_javabase, bool mode_flag_cmd_line) NOT_CDS_RETURN_(true); static const char* type_of_archive_being_loaded(); static const char* type_of_archive_being_written(); + static void prepare_for_dumping(); // --- Basic CDS features // archive(s) in general static bool is_dumping_archive() { return is_dumping_static_archive() || is_dumping_dynamic_archive(); } + + // input archive(s) static bool is_using_archive() NOT_CDS_RETURN_(false); - static int num_archives(const char* archive_path) NOT_CDS_RETURN_(0); // static_archive static bool is_dumping_static_archive() { return CDS_ONLY(_is_dumping_static_archive) NOT_CDS(false); } @@ -125,7 +134,7 @@ public: // dynamic_archive static bool is_dumping_dynamic_archive() { return CDS_ONLY(_is_dumping_dynamic_archive) NOT_CDS(false); } - static void enable_dumping_dynamic_archive() { CDS_ONLY(_is_dumping_dynamic_archive = true); } + static void enable_dumping_dynamic_archive(const char* output_path) NOT_CDS_RETURN; static void disable_dumping_dynamic_archive() { CDS_ONLY(_is_dumping_dynamic_archive = false); } // Misc CDS features @@ -147,12 +156,11 @@ public: // archive_path - // Points to the classes.jsa in $JAVA_HOME - static char* default_archive_path() NOT_CDS_RETURN_(nullptr); - // The actual static archive (if any) selected at runtime - static const char* static_archive_path() { return CDS_ONLY(_static_archive_path) NOT_CDS(nullptr); } - // The actual dynamic archive (if any) selected at runtime - static const char* dynamic_archive_path() { return CDS_ONLY(_dynamic_archive_path) NOT_CDS(nullptr); } + // Points to the classes.jsa in $JAVA_HOME (could be input or output) + static const char* default_archive_path() NOT_CDS_RETURN_(nullptr); + static const char* input_static_archive_path() { return CDS_ONLY(_input_static_archive_path) NOT_CDS(nullptr); } + static const char* input_dynamic_archive_path() { return CDS_ONLY(_input_dynamic_archive_path) NOT_CDS(nullptr); } + static const char* output_archive_path() { return CDS_ONLY(_output_archive_path) NOT_CDS(nullptr); } // --- Archived java objects diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp index c3a6db9e9b9..bf4257253e8 100644 --- a/src/hotspot/share/cds/dynamicArchive.cpp +++ b/src/hotspot/share/cds/dynamicArchive.cpp @@ -97,8 +97,6 @@ public: void gather_array_klasses(); public: - DynamicArchiveBuilder() : ArchiveBuilder() { } - // Do this before and after the archive dump to see if any corruption // is caused by dynamic dumping. void verify_universe(const char* info) { @@ -348,7 +346,7 @@ void DynamicArchiveBuilder::write_archive(char* serialized_data, AOTClassLocatio FileMapInfo* dynamic_info = FileMapInfo::dynamic_info(); assert(dynamic_info != nullptr, "Sanity"); - dynamic_info->open_for_write(); + dynamic_info->open_as_output(); ArchiveHeapInfo no_heap_for_dynamic_dump; ArchiveBuilder::write_archive(dynamic_info, &no_heap_for_dynamic_dump); @@ -476,27 +474,6 @@ int DynamicArchive::num_array_klasses() { return _array_klasses != nullptr ? _array_klasses->length() : 0; } -void DynamicArchive::check_for_dynamic_dump() { - if (CDSConfig::is_dumping_dynamic_archive() && !CDSConfig::is_using_archive()) { - // This could happen if SharedArchiveFile has failed to load: - // - -Xshare:off was specified - // - SharedArchiveFile points to an non-existent file. - // - SharedArchiveFile points to an archive that has failed CRC check - // - SharedArchiveFile is not specified and the VM doesn't have a compatible default archive - -#define __THEMSG " is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info." - if (RecordDynamicDumpInfo) { - log_error(cds)("-XX:+RecordDynamicDumpInfo%s", __THEMSG); - MetaspaceShared::unrecoverable_loading_error(); - } else { - assert(ArchiveClassesAtExit != nullptr, "sanity"); - log_warning(cds)("-XX:ArchiveClassesAtExit" __THEMSG); - } -#undef __THEMSG - CDSConfig::disable_dumping_dynamic_archive(); - } -} - void DynamicArchive::dump_impl(bool jcmd_request, const char* archive_name, TRAPS) { MetaspaceShared::link_shared_classes(CHECK); if (!jcmd_request && CDSConfig::is_dumping_regenerated_lambdaform_invokers()) { @@ -507,11 +484,12 @@ void DynamicArchive::dump_impl(bool jcmd_request, const char* archive_name, TRAP VMThread::execute(&op); } -void DynamicArchive::dump_at_exit(JavaThread* current, const char* archive_name) { +void DynamicArchive::dump_at_exit(JavaThread* current) { ExceptionMark em(current); ResourceMark rm(current); CDSConfig::DumperThreadMark dumper_thread_mark(current); + const char* archive_name = CDSConfig::output_archive_path(); if (!CDSConfig::is_dumping_dynamic_archive() || archive_name == nullptr) { return; } diff --git a/src/hotspot/share/cds/dynamicArchive.hpp b/src/hotspot/share/cds/dynamicArchive.hpp index 905c511c4e0..8c23750734c 100644 --- a/src/hotspot/share/cds/dynamicArchive.hpp +++ b/src/hotspot/share/cds/dynamicArchive.hpp @@ -63,9 +63,8 @@ private: static GrowableArray* _array_klasses; static Array* _dynamic_archive_array_klasses; public: - static void check_for_dynamic_dump(); static void dump_for_jcmd(const char* archive_name, TRAPS); - static void dump_at_exit(JavaThread* current, const char* archive_name); + static void dump_at_exit(JavaThread* current); static void dump_impl(bool jcmd_request, const char* archive_name, TRAPS); static bool is_mapped() { return FileMapInfo::dynamic_info() != nullptr; } static bool validate(FileMapInfo* dynamic_info); diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index ebcd33f8bd5..580699b60b5 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -173,7 +173,7 @@ void FileMapInfo::populate_header(size_t core_region_alignment) { header_size = c_header_size; const char* default_base_archive_name = CDSConfig::default_archive_path(); - const char* current_base_archive_name = CDSConfig::static_archive_path(); + const char* current_base_archive_name = CDSConfig::input_static_archive_path(); if (!os::same_files(current_base_archive_name, default_base_archive_name)) { base_archive_name_size = strlen(current_base_archive_name) + 1; header_size += base_archive_name_size; @@ -209,7 +209,7 @@ void FileMapHeader::populate(FileMapInfo *info, size_t core_region_alignment, if (!info->is_static() && base_archive_name_size != 0) { // copy base archive name - copy_base_archive_name(CDSConfig::static_archive_path()); + copy_base_archive_name(CDSConfig::input_static_archive_path()); } _core_region_alignment = core_region_alignment; _obj_alignment = ObjectAlignmentInBytes; @@ -563,7 +563,7 @@ public: // true && (*base_archive_name) != nullptr: // is a valid dynamic archive. bool FileMapInfo::get_base_archive_name_from_header(const char* archive_name, - char** base_archive_name) { + const char** base_archive_name) { FileHeaderHelper file_helper(archive_name, false); *base_archive_name = nullptr; @@ -619,7 +619,7 @@ bool FileMapInfo::init_from_file(int fd) { // Good } else { if (CDSConfig::new_aot_flags_used()) { - log_warning(cds)("Not a valid %s %s", file_type, _full_path); + log_warning(cds)("Not a valid %s (%s)", file_type, _full_path); } else { log_warning(cds)("Not a base shared archive: %s", _full_path); } @@ -729,7 +729,7 @@ bool FileMapInfo::open_for_read() { // Write the FileMapInfo information to the file. -void FileMapInfo::open_for_write() { +void FileMapInfo::open_as_output() { LogMessage(cds) msg; if (msg.is_info()) { if (CDSConfig::is_dumping_preimage_static_archive()) { @@ -1759,7 +1759,7 @@ bool FileMapInfo::_memory_mapping_failed = false; // [1] validate_header() - done here. // [2] validate_shared_path_table - this is done later, because the table is in the RO // region of the archive, which is not mapped yet. -bool FileMapInfo::initialize() { +bool FileMapInfo::open_as_input() { assert(CDSConfig::is_using_archive(), "UseSharedSpaces expected."); assert(Arguments::has_jimage(), "The shared archive file cannot be used with an exploded module build."); @@ -1774,13 +1774,12 @@ bool FileMapInfo::initialize() { if (!open_for_read() || !init_from_file(_fd) || !validate_header()) { if (_is_static) { - log_info(cds)("Initialize static archive failed."); + log_info(cds)("Loading static archive failed."); return false; } else { - log_info(cds)("Initialize dynamic archive failed."); + log_info(cds)("Loading dynamic archive failed."); if (AutoCreateSharedArchive) { - CDSConfig::enable_dumping_dynamic_archive(); - ArchiveClassesAtExit = CDSConfig::dynamic_archive_path(); + CDSConfig::enable_dumping_dynamic_archive(_full_path); } return false; } diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index 50af87a5da7..8793e110948 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -268,7 +268,7 @@ private: public: FileMapHeader *header() const { return _header; } static bool get_base_archive_name_from_header(const char* archive_name, - char** base_archive_name); + const char** base_archive_name); static bool is_preimage_static_archive(const char* file); bool init_from_file(int fd); @@ -346,9 +346,8 @@ public: static void assert_mark(bool check); // File manipulation. - bool initialize() NOT_CDS_RETURN_(false); - bool open_for_read(); - void open_for_write(); + bool open_as_input() NOT_CDS_RETURN_(false); + void open_as_output(); void write_header(); void write_region(int region, char* base, size_t size, bool read_only, bool allow_exec); @@ -425,6 +424,7 @@ public: } private: + bool open_for_read(); void seek_to_position(size_t pos); bool map_heap_region_impl() NOT_CDS_JAVA_HEAP_RETURN_(false); void dealloc_heap_region() NOT_CDS_JAVA_HEAP_RETURN; diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index 85916ced3cf..ef2a6dcb8e6 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -678,14 +678,11 @@ void VM_PopulateDumpSharedSpace::doit() { CppVtables::zero_archived_vtables(); // Write the archive file - const char* static_archive; if (CDSConfig::is_dumping_final_static_archive()) { - static_archive = AOTCache; - FileMapInfo::free_current_info(); - } else { - static_archive = CDSConfig::static_archive_path(); + FileMapInfo::free_current_info(); // FIXME: should not free current info } - assert(static_archive != nullptr, "SharedArchiveFile not set?"); + const char* static_archive = CDSConfig::output_archive_path(); + assert(static_archive != nullptr, "sanity"); _map_info = new FileMapInfo(static_archive, true); _map_info->populate_header(MetaspaceShared::core_region_alignment()); _map_info->set_early_serialized_data(early_serialized_data); @@ -789,11 +786,6 @@ void MetaspaceShared::link_shared_classes(TRAPS) { } } -void MetaspaceShared::prepare_for_dumping() { - assert(CDSConfig::is_dumping_archive(), "sanity"); - CDSConfig::check_unsupported_dumping_module_options(); -} - // Preload classes from a list, populate the shared spaces and dump to a // file. void MetaspaceShared::preload_and_dump(TRAPS) { @@ -1023,7 +1015,7 @@ bool MetaspaceShared::write_static_archive(ArchiveBuilder* builder, FileMapInfo* // without runtime relocation. builder->relocate_to_requested(); - map_info->open_for_write(); + map_info->open_as_output(); if (!map_info->is_open()) { return false; } @@ -1214,10 +1206,10 @@ void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() { } FileMapInfo* MetaspaceShared::open_static_archive() { - const char* static_archive = CDSConfig::static_archive_path(); + const char* static_archive = CDSConfig::input_static_archive_path(); assert(static_archive != nullptr, "sanity"); FileMapInfo* mapinfo = new FileMapInfo(static_archive, true); - if (!mapinfo->initialize()) { + if (!mapinfo->open_as_input()) { delete(mapinfo); return nullptr; } @@ -1228,13 +1220,13 @@ FileMapInfo* MetaspaceShared::open_dynamic_archive() { if (CDSConfig::is_dumping_dynamic_archive()) { return nullptr; } - const char* dynamic_archive = CDSConfig::dynamic_archive_path(); + const char* dynamic_archive = CDSConfig::input_dynamic_archive_path(); if (dynamic_archive == nullptr) { return nullptr; } FileMapInfo* mapinfo = new FileMapInfo(dynamic_archive, false); - if (!mapinfo->initialize()) { + if (!mapinfo->open_as_input()) { delete(mapinfo); if (RequireSharedSpaces) { MetaspaceShared::unrecoverable_loading_error("Failed to initialize dynamic archive"); @@ -1817,7 +1809,7 @@ void MetaspaceShared::initialize_shared_spaces() { if (PrintSharedArchiveAndExit) { // Print archive names if (dynamic_mapinfo != nullptr) { - tty->print_cr("\n\nBase archive name: %s", CDSConfig::static_archive_path()); + tty->print_cr("\n\nBase archive name: %s", CDSConfig::input_static_archive_path()); tty->print_cr("Base archive version %d", static_mapinfo->version()); } else { tty->print_cr("Static archive name: %s", static_mapinfo->full_path()); diff --git a/src/hotspot/share/cds/metaspaceShared.hpp b/src/hotspot/share/cds/metaspaceShared.hpp index 8881dc6d6fd..e03994be1b9 100644 --- a/src/hotspot/share/cds/metaspaceShared.hpp +++ b/src/hotspot/share/cds/metaspaceShared.hpp @@ -71,7 +71,6 @@ class MetaspaceShared : AllStatic { n_regions = 4 // total number of regions }; - static void prepare_for_dumping() NOT_CDS_RETURN; static void preload_and_dump(TRAPS) NOT_CDS_RETURN; #ifdef _LP64 static void adjust_heap_sizes_for_dumping() NOT_CDS_JAVA_HEAP_RETURN; diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp index fe9c960b7f2..6f415ab93a4 100644 --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -897,14 +897,13 @@ jint universe_init() { ClassLoaderData::init_null_class_loader_data(); #if INCLUDE_CDS - DynamicArchive::check_for_dynamic_dump(); if (CDSConfig::is_using_archive()) { // Read the data structures supporting the shared spaces (shared // system dictionary, symbol table, etc.) MetaspaceShared::initialize_shared_spaces(); } if (CDSConfig::is_dumping_archive()) { - MetaspaceShared::prepare_for_dumping(); + CDSConfig::prepare_for_dumping(); } #endif diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 0927e87c748..d2e3df71dc4 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -3708,7 +3708,7 @@ jint Arguments::apply_ergo() { CompressedKlassPointers::pre_initialize(); } - CDSConfig::initialize(); + CDSConfig::ergo_initialize(); // Initialize Metaspace flags and alignments Metaspace::ergo_initialize(); diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index bcf99c84ba4..b3ad15ae3ff 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -426,11 +426,10 @@ void before_exit(JavaThread* thread, bool halt) { #if INCLUDE_CDS // Dynamic CDS dumping must happen whilst we can still reliably // run Java code. - DynamicArchive::dump_at_exit(thread, ArchiveClassesAtExit); + DynamicArchive::dump_at_exit(thread); assert(!thread->has_pending_exception(), "must be"); #endif - // Actual shutdown logic begins here. #if INCLUDE_JVMCI diff --git a/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c b/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c index bcce23f1221..3c244aab0f3 100644 --- a/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c +++ b/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -265,7 +265,7 @@ bool read_string(struct ps_prochandle* ph, uintptr_t addr, char* buf, size_t siz #ifdef LINUX // mangled name of CDSConfig::_static_archive_path -#define SHARED_ARCHIVE_PATH_SYM "_ZN9CDSConfig20_static_archive_pathE" +#define SHARED_ARCHIVE_PATH_SYM "_ZN9CDSConfig26_input_static_archive_pathE" #define USE_SHARED_SPACES_SYM "UseSharedSpaces" #define SHARED_BASE_ADDRESS_SYM "SharedBaseAddress" #define LIBJVM_NAME "/libjvm.so" @@ -273,7 +273,7 @@ bool read_string(struct ps_prochandle* ph, uintptr_t addr, char* buf, size_t siz #ifdef __APPLE__ // mangled name of CDSConfig::_static_archive_path -#define SHARED_ARCHIVE_PATH_SYM "__ZN9CDSConfig20_static_archive_pathE" +#define SHARED_ARCHIVE_PATH_SYM "__ZN9CDSConfig26_input_static_archive_pathE" #define USE_SHARED_SPACES_SYM "_UseSharedSpaces" #define SHARED_BASE_ADDRESS_SYM "_SharedBaseAddress" #define LIBJVM_NAME "/libjvm.dylib" diff --git a/test/hotspot/jtreg/runtime/cds/appcds/AOTFlags.java b/test/hotspot/jtreg/runtime/cds/appcds/AOTFlags.java index aeb0476346d..46f76fab368 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/AOTFlags.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/AOTFlags.java @@ -26,12 +26,14 @@ * @test * @summary "AOT" aliases for traditional CDS command-line options * @requires vm.cds + * @requires vm.flagless * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes * @build Hello * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar hello.jar Hello * @run driver AOTFlags */ +import java.io.File; import jdk.test.lib.cds.CDSTestUtils; import jdk.test.lib.helpers.ClassFileInstaller; import jdk.test.lib.process.OutputAnalyzer; @@ -298,6 +300,60 @@ public class AOTFlags { "specified when the AOTConfiguration file was recorded"); out.shouldContain("Unable to use create AOT cache"); out.shouldHaveExitValue(1); + + //---------------------------------------------------------------------- + printTestCase("Cannot use multiple paths in AOTConfiguration"); + + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTMode=record", + "-XX:AOTConfiguration=" + aotConfigFile + File.pathSeparator + "dummy", + "-cp", "noSuchJar.jar"); + + out = CDSTestUtils.executeAndLog(pb, "neg"); + out.shouldContain("Option AOTConfiguration must specify a single file name"); + out.shouldHaveExitValue(1); + + //---------------------------------------------------------------------- + printTestCase("Cannot use multiple paths in AOTCache"); + + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:AOTMode=create", + "-XX:AOTConfiguration=" + aotConfigFile, + "-XX:AOTCache=" + aotCacheFile + File.pathSeparator + "dummy", + "-cp", "noSuchJar.jar"); + + out = CDSTestUtils.executeAndLog(pb, "neg"); + out.shouldContain("Option AOTCache must specify a single file name"); + out.shouldHaveExitValue(1); + + //---------------------------------------------------------------------- + printTestCase("Cannot use a dynamic CDS archive for -XX:AOTCache"); + String staticArchive = "static.jsa"; + String dynamicArchive = "dynamic.jsa"; + + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-Xshare:dump", + "-XX:SharedArchiveFile=" + staticArchive); + out = CDSTestUtils.executeAndLog(pb, "static"); + out.shouldHaveExitValue(0); + + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:SharedArchiveFile=" + staticArchive, + "-XX:ArchiveClassesAtExit=" + dynamicArchive, + "--version"); + out = CDSTestUtils.executeAndLog(pb, "dynamic"); + out.shouldHaveExitValue(0); + + pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-Xlog:cds", + "-XX:AOTMode=on", + "-XX:AOTCache=" + dynamicArchive, + "--version"); + + out = CDSTestUtils.executeAndLog(pb, "neg"); + out.shouldContain("Unable to use AOT cache."); + out.shouldContain("Not a valid AOT cache (dynamic.jsa)"); + out.shouldHaveExitValue(1); } static int testNum = 0; diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java index c8a04027a3d..3bc1e395b17 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchive.java @@ -337,7 +337,7 @@ public class TestAutoCreateSharedArchive extends DynamicArchiveTestBase { .shouldContain(HELLO_WORLD) .shouldContain("The shared archive file version " + hex(version2) + " does not match the required version " + hex(currentCDSVersion)) .shouldContain("The shared archive file has the wrong version") - .shouldContain("Initialize dynamic archive failed") + .shouldContain("Loading dynamic archive failed") .shouldContain("Dumping shared data to file"); }); ft2 = Files.getLastModifiedTime(Paths.get(modVersion)); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java index 133f44521d5..4806f571dc6 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveNoDefaultArchive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -112,7 +112,7 @@ public class TestAutoCreateSharedArchiveNoDefaultArchive { "-version"); TestCommon.executeAndLog(pb, "show-version") .shouldHaveExitValue(0) - .shouldContain("Initialize static archive failed") + .shouldContain("Loading static archive failed") .shouldContain("Unable to map shared spaces") .shouldNotContain("sharing"); } @@ -132,7 +132,7 @@ public class TestAutoCreateSharedArchiveNoDefaultArchive { mainClass); TestCommon.executeAndLog(pb, "no-default-archive") .shouldHaveExitValue(0) - .shouldContain("Initialize static archive failed") + .shouldContain("Loading static archive failed") .shouldContain("Unable to map shared spaces") .shouldNotContain("Dumping shared data to file"); if (jsaFile.exists()) {