@@ -51,9 +51,10 @@ bool CDSConfig::_old_cds_flags_used = false;
51
51
bool CDSConfig::_new_aot_flags_used = false ;
52
52
bool CDSConfig::_disable_heap_dumping = false ;
53
53
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 ;
57
58
58
59
JavaThread* CDSConfig::_dumper_thread = nullptr ;
59
60
@@ -66,7 +67,11 @@ int CDSConfig::get_status() {
66
67
(is_using_archive () ? IS_USING_ARCHIVE : 0 );
67
68
}
68
69
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
+
70
75
if (is_dumping_static_archive () && !is_dumping_final_static_archive ()) {
71
76
// Note: -Xshare and -XX:AOTMode flags are mutually exclusive.
72
77
// - Classic workflow: -Xshare:on and -Xshare:dump cannot take effect at the same time.
@@ -83,18 +88,23 @@ void CDSConfig::initialize() {
83
88
84
89
// Initialize shared archive paths which could include both base and dynamic archive paths
85
90
// 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.
88
91
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
+ }
90
97
}
91
98
92
99
if (!is_dumping_heap ()) {
93
100
_is_dumping_full_module_graph = false ;
94
101
}
95
102
}
96
103
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" );
98
108
if (_default_archive_path == nullptr ) {
99
109
stringStream tmp;
100
110
const char * subdir = WINDOWS_ONLY (" bin" ) NOT_WINDOWS (" lib" );
@@ -116,12 +126,12 @@ char* CDSConfig::default_archive_path() {
116
126
return _default_archive_path;
117
127
}
118
128
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 ) {
121
131
return 0 ;
122
132
}
123
133
int npaths = 1 ;
124
- char * p = (char *)archive_path ;
134
+ char * p = (char *)path_spec ;
125
135
while (*p != ' \0 ' ) {
126
136
if (*p == os::path_separator ()[0 ]) {
127
137
npaths++;
@@ -131,9 +141,9 @@ int CDSConfig::num_archives(const char* archive_path) {
131
141
return npaths;
132
142
}
133
143
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) {
137
147
char * begin_ptr = (char *)archive_path;
138
148
char * end_ptr = strchr ((char *)archive_path, os::path_separator ()[0 ]);
139
149
if (end_ptr == nullptr || end_ptr == begin_ptr) {
@@ -157,7 +167,8 @@ void CDSConfig::extract_shared_archive_paths(const char* archive_path,
157
167
*top_archive_path = cur_path;
158
168
}
159
169
160
- void CDSConfig::init_shared_archive_paths () {
170
+ void CDSConfig::ergo_init_classic_archive_paths () {
171
+ assert (_cds_ergo_initialize_started, " sanity" );
161
172
if (ArchiveClassesAtExit != nullptr ) {
162
173
assert (!RecordDynamicDumpInfo, " already checked" );
163
174
if (is_dumping_static_archive ()) {
@@ -172,21 +183,24 @@ void CDSConfig::init_shared_archive_paths() {
172
183
}
173
184
174
185
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
+ }
176
190
} 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" );
179
193
180
- if (is_dumping_archive () && archives > 1 ) {
194
+ if (is_dumping_archive () && num_archives > 1 ) {
181
195
vm_exit_during_initialization (
182
196
" Cannot have more than 1 archive file specified in -XX:SharedArchiveFile during CDS dumping" );
183
197
}
184
198
185
199
if (is_dumping_static_archive ()) {
186
- assert (archives == 1 , " must be " );
200
+ assert (num_archives == 1 , " just checked above " );
187
201
// 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;
190
204
} else {
191
205
// SharedArchiveFile may specify one or two files. In case (c), the path for base.jsa
192
206
// is read from top.jsa
@@ -197,48 +211,49 @@ void CDSConfig::init_shared_archive_paths() {
197
211
// However, if either RecordDynamicDumpInfo or ArchiveClassesAtExit is used, we do not
198
212
// allow cases (b) and (c). Case (b) is already checked above.
199
213
200
- if (archives > 2 ) {
214
+ if (num_archives > 2 ) {
201
215
vm_exit_during_initialization (
202
216
" Cannot have more than 2 archive files specified in the -XX:SharedArchiveFile option" );
203
217
}
204
- if (archives == 1 ) {
205
- char * base_archive_path = nullptr ;
218
+
219
+ if (num_archives == 1 ) {
220
+ const char * base_archive_path = nullptr ;
206
221
bool success =
207
222
FileMapInfo::get_base_archive_name_from_header (SharedArchiveFile, &base_archive_path);
208
223
if (!success) {
209
224
// If +AutoCreateSharedArchive and the specified shared archive does not exist,
210
225
// regenerate the dynamic archive base on default archive.
211
226
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 {
217
232
if (AutoCreateSharedArchive) {
218
233
warning (" -XX:+AutoCreateSharedArchive is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info." );
219
234
AutoCreateSharedArchive = false ;
220
235
}
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);
222
237
Arguments::no_shared_spaces (" invalid archive" );
223
238
}
224
239
} else if (base_archive_path == nullptr ) {
225
240
// 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;
227
242
} else {
228
243
// 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.
231
246
}
232
247
} 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" );
237
252
Arguments::no_shared_spaces (" invalid archive" );
238
253
}
239
254
}
240
255
241
- if (_dynamic_archive_path != nullptr ) {
256
+ if (_input_dynamic_archive_path != nullptr ) {
242
257
// Check for case (c)
243
258
if (RecordDynamicDumpInfo) {
244
259
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() {
353
368
return false ;
354
369
}
355
370
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)
357
372
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 ) {
360
375
vm_exit_during_initialization (err_msg (" Option %s cannot be used at the same time with "
361
376
" -Xshare:on, -Xshare:auto, -Xshare:off, -Xshare:dump, "
362
377
" 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));
364
387
}
365
388
}
366
389
@@ -371,9 +394,13 @@ void CDSConfig::check_aot_flags() {
371
394
_old_cds_flags_used = true ;
372
395
}
373
396
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);
377
404
378
405
if (FLAG_IS_DEFAULT (AOTCache) && FLAG_IS_DEFAULT (AOTConfiguration) && FLAG_IS_DEFAULT (AOTMode)) {
379
406
// AOTCache/AOTConfiguration/AOTMode not used.
@@ -411,11 +438,6 @@ void CDSConfig::check_aotmode_auto_or_on() {
411
438
vm_exit_during_initialization (" AOTConfiguration can only be used with -XX:AOTMode=record or -XX:AOTMode=create" );
412
439
}
413
440
414
- if (!FLAG_IS_DEFAULT (AOTCache)) {
415
- assert (FLAG_IS_DEFAULT (SharedArchiveFile), " already checked" );
416
- FLAG_SET_ERGO (SharedArchiveFile, AOTCache);
417
- }
418
-
419
441
UseSharedSpaces = true ;
420
442
if (FLAG_IS_DEFAULT (AOTMode) || (strcmp (AOTMode, " auto" ) == 0 )) {
421
443
RequireSharedSpaces = false ;
@@ -430,10 +452,6 @@ void CDSConfig::check_aotmode_record() {
430
452
vm_exit_during_initialization (" AOTCache must not be specified when using -XX:AOTMode=record" );
431
453
}
432
454
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 );
437
455
UseSharedSpaces = false ;
438
456
RequireSharedSpaces = false ;
439
457
_is_dumping_static_archive = true ;
@@ -449,10 +467,7 @@ void CDSConfig::check_aotmode_create() {
449
467
vm_exit_during_initialization (" AOTCache must be specified when using -XX:AOTMode=create" );
450
468
}
451
469
452
- assert (FLAG_IS_DEFAULT (SharedArchiveFile), " already checked" );
453
-
454
470
_is_dumping_final_static_archive = true ;
455
- FLAG_SET_ERGO (SharedArchiveFile, AOTConfiguration);
456
471
UseSharedSpaces = true ;
457
472
RequireSharedSpaces = true ;
458
473
@@ -463,7 +478,29 @@ void CDSConfig::check_aotmode_create() {
463
478
CDSConfig::enable_dumping_static_archive ();
464
479
}
465
480
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
+
466
501
bool 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
+
467
504
check_aot_flags ();
468
505
469
506
if (!FLAG_IS_DEFAULT (AOTMode)) {
@@ -514,7 +551,7 @@ bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_fla
514
551
if (ArchiveClassesAtExit == nullptr && !RecordDynamicDumpInfo) {
515
552
disable_dumping_dynamic_archive ();
516
553
} else {
517
- enable_dumping_dynamic_archive ();
554
+ enable_dumping_dynamic_archive (ArchiveClassesAtExit );
518
555
}
519
556
520
557
if (AutoCreateSharedArchive) {
@@ -546,6 +583,34 @@ bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_fla
546
583
return true ;
547
584
}
548
585
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
+
549
614
bool CDSConfig::is_dumping_classic_static_archive () {
550
615
return _is_dumping_static_archive &&
551
616
!is_dumping_preimage_static_archive () &&
@@ -560,6 +625,18 @@ bool CDSConfig::is_dumping_final_static_archive() {
560
625
return _is_dumping_final_static_archive;
561
626
}
562
627
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
+
563
640
bool CDSConfig::allow_only_single_java_thread () {
564
641
// See comments in JVM_StartThread()
565
642
return is_dumping_classic_static_archive () || is_dumping_final_static_archive ();
0 commit comments