@@ -51,9 +51,10 @@ bool CDSConfig::_old_cds_flags_used = false;
5151bool CDSConfig::_new_aot_flags_used = false ;
5252bool CDSConfig::_disable_heap_dumping = false ;
5353
54- char * CDSConfig::_default_archive_path = nullptr ;
55- char * CDSConfig::_static_archive_path = nullptr ;
56- char * CDSConfig::_dynamic_archive_path = nullptr ;
54+ const char * CDSConfig::_default_archive_path = nullptr ;
55+ const char * CDSConfig::_input_static_archive_path = nullptr ;
56+ const char * CDSConfig::_input_dynamic_archive_path = nullptr ;
57+ const char * CDSConfig::_output_archive_path = nullptr ;
5758
5859JavaThread* CDSConfig::_dumper_thread = nullptr ;
5960
@@ -66,7 +67,11 @@ int CDSConfig::get_status() {
6667 (is_using_archive () ? IS_USING_ARCHIVE : 0 );
6768}
6869
69- void CDSConfig::initialize () {
70+ DEBUG_ONLY (static bool _cds_ergo_initialize_started = false );
71+
72+ void CDSConfig::ergo_initialize () {
73+ DEBUG_ONLY (_cds_ergo_initialize_started = true );
74+
7075 if (is_dumping_static_archive () && !is_dumping_final_static_archive ()) {
7176 // Note: -Xshare and -XX:AOTMode flags are mutually exclusive.
7277 // - Classic workflow: -Xshare:on and -Xshare:dump cannot take effect at the same time.
@@ -83,18 +88,23 @@ void CDSConfig::initialize() {
8388
8489 // Initialize shared archive paths which could include both base and dynamic archive paths
8590 // This must be after set_ergonomics_flags() called so flag UseCompressedOops is set properly.
86- //
87- // UseSharedSpaces may be disabled if -XX:SharedArchiveFile is invalid.
8891 if (is_dumping_static_archive () || is_using_archive ()) {
89- init_shared_archive_paths ();
92+ if (new_aot_flags_used ()) {
93+ ergo_init_aot_paths ();
94+ } else {
95+ ergo_init_classic_archive_paths ();
96+ }
9097 }
9198
9299 if (!is_dumping_heap ()) {
93100 _is_dumping_full_module_graph = false ;
94101 }
95102}
96103
97- char * CDSConfig::default_archive_path () {
104+ const char * CDSConfig::default_archive_path () {
105+ // The path depends on UseCompressedOops, etc, which are set by GC ergonomics just
106+ // before CDSConfig::ergo_initialize() is called.
107+ assert (_cds_ergo_initialize_started, " sanity" );
98108 if (_default_archive_path == nullptr ) {
99109 stringStream tmp;
100110 const char * subdir = WINDOWS_ONLY (" bin" ) NOT_WINDOWS (" lib" );
@@ -116,12 +126,12 @@ char* CDSConfig::default_archive_path() {
116126 return _default_archive_path;
117127}
118128
119- int CDSConfig::num_archives (const char * archive_path ) {
120- if (archive_path == nullptr ) {
129+ int CDSConfig::num_archive_paths (const char * path_spec ) {
130+ if (path_spec == nullptr ) {
121131 return 0 ;
122132 }
123133 int npaths = 1 ;
124- char * p = (char *)archive_path ;
134+ char * p = (char *)path_spec ;
125135 while (*p != ' \0 ' ) {
126136 if (*p == os::path_separator ()[0 ]) {
127137 npaths++;
@@ -131,9 +141,9 @@ int CDSConfig::num_archives(const char* archive_path) {
131141 return npaths;
132142}
133143
134- void CDSConfig::extract_shared_archive_paths (const char * archive_path,
135- char ** base_archive_path,
136- char ** top_archive_path) {
144+ void CDSConfig::extract_archive_paths (const char * archive_path,
145+ const char ** base_archive_path,
146+ const char ** top_archive_path) {
137147 char * begin_ptr = (char *)archive_path;
138148 char * end_ptr = strchr ((char *)archive_path, os::path_separator ()[0 ]);
139149 if (end_ptr == nullptr || end_ptr == begin_ptr) {
@@ -157,7 +167,8 @@ void CDSConfig::extract_shared_archive_paths(const char* archive_path,
157167 *top_archive_path = cur_path;
158168}
159169
160- void CDSConfig::init_shared_archive_paths () {
170+ void CDSConfig::ergo_init_classic_archive_paths () {
171+ assert (_cds_ergo_initialize_started, " sanity" );
161172 if (ArchiveClassesAtExit != nullptr ) {
162173 assert (!RecordDynamicDumpInfo, " already checked" );
163174 if (is_dumping_static_archive ()) {
@@ -172,21 +183,24 @@ void CDSConfig::init_shared_archive_paths() {
172183 }
173184
174185 if (SharedArchiveFile == nullptr ) {
175- _static_archive_path = default_archive_path ();
186+ _input_static_archive_path = default_archive_path ();
187+ if (is_dumping_static_archive ()) {
188+ _output_archive_path = _input_static_archive_path;
189+ }
176190 } else {
177- int archives = num_archives (SharedArchiveFile);
178- assert (archives > 0 , " must be" );
191+ int num_archives = num_archive_paths (SharedArchiveFile);
192+ assert (num_archives > 0 , " must be" );
179193
180- if (is_dumping_archive () && archives > 1 ) {
194+ if (is_dumping_archive () && num_archives > 1 ) {
181195 vm_exit_during_initialization (
182196 " Cannot have more than 1 archive file specified in -XX:SharedArchiveFile during CDS dumping" );
183197 }
184198
185199 if (is_dumping_static_archive ()) {
186- assert (archives == 1 , " must be " );
200+ assert (num_archives == 1 , " just checked above " );
187201 // Static dump is simple: only one archive is allowed in SharedArchiveFile. This file
188- // will be overwritten no matter regardless of its contents
189- _static_archive_path = os::strdup_check_oom ( SharedArchiveFile, mtArguments) ;
202+ // will be overwritten regardless of its contents
203+ _output_archive_path = SharedArchiveFile;
190204 } else {
191205 // SharedArchiveFile may specify one or two files. In case (c), the path for base.jsa
192206 // is read from top.jsa
@@ -197,48 +211,49 @@ void CDSConfig::init_shared_archive_paths() {
197211 // However, if either RecordDynamicDumpInfo or ArchiveClassesAtExit is used, we do not
198212 // allow cases (b) and (c). Case (b) is already checked above.
199213
200- if (archives > 2 ) {
214+ if (num_archives > 2 ) {
201215 vm_exit_during_initialization (
202216 " Cannot have more than 2 archive files specified in the -XX:SharedArchiveFile option" );
203217 }
204- if (archives == 1 ) {
205- char * base_archive_path = nullptr ;
218+
219+ if (num_archives == 1 ) {
220+ const char * base_archive_path = nullptr ;
206221 bool success =
207222 FileMapInfo::get_base_archive_name_from_header (SharedArchiveFile, &base_archive_path);
208223 if (!success) {
209224 // If +AutoCreateSharedArchive and the specified shared archive does not exist,
210225 // regenerate the dynamic archive base on default archive.
211226 if (AutoCreateSharedArchive && !os::file_exists (SharedArchiveFile)) {
212- enable_dumping_dynamic_archive ();
213- ArchiveClassesAtExit = const_cast < char *>( SharedArchiveFile);
214- _static_archive_path = default_archive_path ();
215- SharedArchiveFile = nullptr ;
216- } else {
227+ enable_dumping_dynamic_archive (SharedArchiveFile );
228+ FLAG_SET_ERGO ( ArchiveClassesAtExit, SharedArchiveFile);
229+ _input_static_archive_path = default_archive_path ();
230+ FLAG_SET_ERGO ( SharedArchiveFile, nullptr ) ;
231+ } else {
217232 if (AutoCreateSharedArchive) {
218233 warning (" -XX:+AutoCreateSharedArchive is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info." );
219234 AutoCreateSharedArchive = false ;
220235 }
221- log_error (cds)(" Not a valid %s (%s)" , new_aot_flags_used () ? " AOT cache " : " archive " , SharedArchiveFile);
236+ log_error (cds)(" Not a valid archive (%s)" , SharedArchiveFile);
222237 Arguments::no_shared_spaces (" invalid archive" );
223238 }
224239 } else if (base_archive_path == nullptr ) {
225240 // User has specified a single archive, which is a static archive.
226- _static_archive_path = const_cast < char *>( SharedArchiveFile) ;
241+ _input_static_archive_path = SharedArchiveFile;
227242 } else {
228243 // User has specified a single archive, which is a dynamic archive.
229- _dynamic_archive_path = const_cast < char *>( SharedArchiveFile) ;
230- _static_archive_path = base_archive_path; // has been c-heap allocated.
244+ _input_dynamic_archive_path = SharedArchiveFile;
245+ _input_static_archive_path = base_archive_path; // has been c-heap allocated.
231246 }
232247 } else {
233- extract_shared_archive_paths (( const char *) SharedArchiveFile,
234- &_static_archive_path , &_dynamic_archive_path );
235- if (_static_archive_path == nullptr ) {
236- assert (_dynamic_archive_path == nullptr , " must be" );
248+ extract_archive_paths ( SharedArchiveFile,
249+ &_input_static_archive_path , &_input_dynamic_archive_path );
250+ if (_input_static_archive_path == nullptr ) {
251+ assert (_input_dynamic_archive_path == nullptr , " must be" );
237252 Arguments::no_shared_spaces (" invalid archive" );
238253 }
239254 }
240255
241- if (_dynamic_archive_path != nullptr ) {
256+ if (_input_dynamic_archive_path != nullptr ) {
242257 // Check for case (c)
243258 if (RecordDynamicDumpInfo) {
244259 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() {
353368 return false ;
354369}
355370
356- #define CHECK_ALIAS (f ) check_flag_alias (FLAG_IS_DEFAULT(f), #f)
371+ #define CHECK_NEW_FLAG (f ) check_new_flag (FLAG_IS_DEFAULT(f), #f)
357372
358- void CDSConfig::check_flag_alias (bool alias_is_default , const char * alias_name ) {
359- if (old_cds_flags_used () && !alias_is_default ) {
373+ void CDSConfig::check_new_flag (bool new_flag_is_default , const char * new_flag_name ) {
374+ if (old_cds_flags_used () && !new_flag_is_default ) {
360375 vm_exit_during_initialization (err_msg (" Option %s cannot be used at the same time with "
361376 " -Xshare:on, -Xshare:auto, -Xshare:off, -Xshare:dump, "
362377 " DumpLoadedClassList, SharedClassListFile, or SharedArchiveFile" ,
363- alias_name));
378+ new_flag_name));
379+ }
380+ }
381+
382+ #define CHECK_SINGLE_PATH (f ) check_flag_single_path(#f, f)
383+
384+ void CDSConfig::check_flag_single_path (const char * flag_name, const char * value) {
385+ if (value != nullptr && num_archive_paths (value) != 1 ) {
386+ vm_exit_during_initialization (err_msg (" Option %s must specify a single file name" , flag_name));
364387 }
365388}
366389
@@ -371,9 +394,13 @@ void CDSConfig::check_aot_flags() {
371394 _old_cds_flags_used = true ;
372395 }
373396
374- CHECK_ALIAS (AOTCache);
375- CHECK_ALIAS (AOTConfiguration);
376- CHECK_ALIAS (AOTMode);
397+ // "New" AOT flags must not be mixed with "classic" flags such as -Xshare:dump
398+ CHECK_NEW_FLAG (AOTCache);
399+ CHECK_NEW_FLAG (AOTConfiguration);
400+ CHECK_NEW_FLAG (AOTMode);
401+
402+ CHECK_SINGLE_PATH (AOTCache);
403+ CHECK_SINGLE_PATH (AOTConfiguration);
377404
378405 if (FLAG_IS_DEFAULT (AOTCache) && FLAG_IS_DEFAULT (AOTConfiguration) && FLAG_IS_DEFAULT (AOTMode)) {
379406 // AOTCache/AOTConfiguration/AOTMode not used.
@@ -411,11 +438,6 @@ void CDSConfig::check_aotmode_auto_or_on() {
411438 vm_exit_during_initialization (" AOTConfiguration can only be used with -XX:AOTMode=record or -XX:AOTMode=create" );
412439 }
413440
414- if (!FLAG_IS_DEFAULT (AOTCache)) {
415- assert (FLAG_IS_DEFAULT (SharedArchiveFile), " already checked" );
416- FLAG_SET_ERGO (SharedArchiveFile, AOTCache);
417- }
418-
419441 UseSharedSpaces = true ;
420442 if (FLAG_IS_DEFAULT (AOTMode) || (strcmp (AOTMode, " auto" ) == 0 )) {
421443 RequireSharedSpaces = false ;
@@ -430,10 +452,6 @@ void CDSConfig::check_aotmode_record() {
430452 vm_exit_during_initialization (" AOTCache must not be specified when using -XX:AOTMode=record" );
431453 }
432454
433- assert (FLAG_IS_DEFAULT (DumpLoadedClassList), " already checked" );
434- assert (FLAG_IS_DEFAULT (SharedArchiveFile), " already checked" );
435- FLAG_SET_ERGO (SharedArchiveFile, AOTConfiguration);
436- FLAG_SET_ERGO (DumpLoadedClassList, nullptr );
437455 UseSharedSpaces = false ;
438456 RequireSharedSpaces = false ;
439457 _is_dumping_static_archive = true ;
@@ -449,10 +467,7 @@ void CDSConfig::check_aotmode_create() {
449467 vm_exit_during_initialization (" AOTCache must be specified when using -XX:AOTMode=create" );
450468 }
451469
452- assert (FLAG_IS_DEFAULT (SharedArchiveFile), " already checked" );
453-
454470 _is_dumping_final_static_archive = true ;
455- FLAG_SET_ERGO (SharedArchiveFile, AOTConfiguration);
456471 UseSharedSpaces = true ;
457472 RequireSharedSpaces = true ;
458473
@@ -463,7 +478,29 @@ void CDSConfig::check_aotmode_create() {
463478 CDSConfig::enable_dumping_static_archive ();
464479}
465480
481+ void CDSConfig::ergo_init_aot_paths () {
482+ assert (_cds_ergo_initialize_started, " sanity" );
483+ if (is_dumping_static_archive ()) {
484+ if (is_dumping_preimage_static_archive ()) {
485+ _output_archive_path = AOTConfiguration;
486+ } else {
487+ assert (is_dumping_final_static_archive (), " must be" );
488+ _input_static_archive_path = AOTConfiguration;
489+ _output_archive_path = AOTCache;
490+ }
491+ } else if (is_using_archive ()) {
492+ if (FLAG_IS_DEFAULT (AOTCache)) {
493+ // Only -XX:AOTMode={auto,on} is specified
494+ _input_static_archive_path = default_archive_path ();
495+ } else {
496+ _input_static_archive_path = AOTCache;
497+ }
498+ }
499+ }
500+
466501bool CDSConfig::check_vm_args_consistency (bool patch_mod_javabase, bool mode_flag_cmd_line) {
502+ assert (!_cds_ergo_initialize_started, " This is called earlier than CDSConfig::ergo_initialize()" );
503+
467504 check_aot_flags ();
468505
469506 if (!FLAG_IS_DEFAULT (AOTMode)) {
@@ -514,7 +551,7 @@ bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_fla
514551 if (ArchiveClassesAtExit == nullptr && !RecordDynamicDumpInfo) {
515552 disable_dumping_dynamic_archive ();
516553 } else {
517- enable_dumping_dynamic_archive ();
554+ enable_dumping_dynamic_archive (ArchiveClassesAtExit );
518555 }
519556
520557 if (AutoCreateSharedArchive) {
@@ -546,6 +583,34 @@ bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_fla
546583 return true ;
547584}
548585
586+ void CDSConfig::prepare_for_dumping () {
587+ assert (CDSConfig::is_dumping_archive (), " sanity" );
588+
589+ if (is_dumping_dynamic_archive () && !is_using_archive ()) {
590+ assert (!is_dumping_static_archive (), " cannot be dumping both static and dynamic archives" );
591+
592+ // This could happen if SharedArchiveFile has failed to load:
593+ // - -Xshare:off was specified
594+ // - SharedArchiveFile points to an non-existent file.
595+ // - SharedArchiveFile points to an archive that has failed CRC check
596+ // - SharedArchiveFile is not specified and the VM doesn't have a compatible default archive
597+
598+ #define __THEMSG " is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info."
599+ if (RecordDynamicDumpInfo) {
600+ log_error (cds)(" -XX:+RecordDynamicDumpInfo%s" , __THEMSG);
601+ MetaspaceShared::unrecoverable_loading_error ();
602+ } else {
603+ assert (ArchiveClassesAtExit != nullptr , " sanity" );
604+ log_warning (cds)(" -XX:ArchiveClassesAtExit" __THEMSG);
605+ }
606+ #undef __THEMSG
607+ disable_dumping_dynamic_archive ();
608+ return ;
609+ }
610+
611+ check_unsupported_dumping_module_options ();
612+ }
613+
549614bool CDSConfig::is_dumping_classic_static_archive () {
550615 return _is_dumping_static_archive &&
551616 !is_dumping_preimage_static_archive () &&
@@ -560,6 +625,18 @@ bool CDSConfig::is_dumping_final_static_archive() {
560625 return _is_dumping_final_static_archive;
561626}
562627
628+ void CDSConfig::enable_dumping_dynamic_archive (const char * output_path) {
629+ _is_dumping_dynamic_archive = true ;
630+ if (output_path == nullptr ) {
631+ // output_path can be null when the VM is started with -XX:+RecordDynamicDumpInfo
632+ // in anticipation of "jcmd VM.cds dynamic_dump", which will provide the actual
633+ // output path.
634+ _output_archive_path = nullptr ;
635+ } else {
636+ _output_archive_path = os::strdup_check_oom (output_path, mtArguments);
637+ }
638+ }
639+
563640bool CDSConfig::allow_only_single_java_thread () {
564641 // See comments in JVM_StartThread()
565642 return is_dumping_classic_static_archive () || is_dumping_final_static_archive ();
0 commit comments