1 /*
  2  * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  *
 23  */
 24 
 25 #include "precompiled.hpp"
 26 #include "cds/archiveHeapLoader.hpp"
 27 #include "cds/cdsConfig.hpp"
 28 #include "cds/classListWriter.hpp"
 29 #include "cds/heapShared.hpp"
 30 #include "classfile/classLoaderDataShared.hpp"
 31 #include "classfile/moduleEntry.hpp"
 32 #include "include/jvm_io.h"
 33 #include "logging/log.hpp"
 34 #include "memory/universe.hpp"
 35 #include "runtime/arguments.hpp"
 36 #include "runtime/globals_extension.hpp"
 37 #include "runtime/java.hpp"
 38 #include "runtime/vmThread.hpp"
 39 #include "utilities/defaultStream.hpp"
 40 #include "utilities/formatBuffer.hpp"
 41 
 42 bool CDSConfig::_is_dumping_static_archive = false;
 43 bool CDSConfig::_is_dumping_dynamic_archive = false;
 44 bool CDSConfig::_is_using_optimized_module_handling = true;
 45 bool CDSConfig::_is_dumping_full_module_graph = true;
 46 bool CDSConfig::_is_using_full_module_graph = true;
 47 bool CDSConfig::_has_aot_linked_classes = false;
 48 bool CDSConfig::_has_archived_invokedynamic = false;
 49 bool CDSConfig::_old_cds_flags_used = false;
 50 
 51 char* CDSConfig::_default_archive_path = nullptr;
 52 char* CDSConfig::_static_archive_path = nullptr;
 53 char* CDSConfig::_dynamic_archive_path = nullptr;
 54 
 55 JavaThread* CDSConfig::_dumper_thread = nullptr;
 56 
 57 int CDSConfig::get_status() {
 58   assert(Universe::is_fully_initialized(), "status is finalized only after Universe is initialized");
 59   return (is_dumping_archive()              ? IS_DUMPING_ARCHIVE : 0) |
 60          (is_dumping_static_archive()       ? IS_DUMPING_STATIC_ARCHIVE : 0) |
 61          (is_logging_lambda_form_invokers() ? IS_LOGGING_LAMBDA_FORM_INVOKERS : 0) |
 62          (is_using_archive()                ? IS_USING_ARCHIVE : 0);
 63 }
 64 
 65 void CDSConfig::initialize() {
 66   if (is_dumping_static_archive()) {
 67     if (RequireSharedSpaces) {
 68       warning("Cannot dump shared archive while using shared archive");
 69     }
 70     UseSharedSpaces = false;
 71   }
 72 
 73   // Initialize shared archive paths which could include both base and dynamic archive paths
 74   // This must be after set_ergonomics_flags() called so flag UseCompressedOops is set properly.
 75   //
 76   // UseSharedSpaces may be disabled if -XX:SharedArchiveFile is invalid.
 77   if (is_dumping_static_archive() || is_using_archive()) {
 78     init_shared_archive_paths();
 79   }
 80 
 81   if (!is_dumping_heap()) {
 82     _is_dumping_full_module_graph = false;
 83   }
 84 }
 85 
 86 char* CDSConfig::default_archive_path() {
 87   if (_default_archive_path == nullptr) {
 88     char jvm_path[JVM_MAXPATHLEN];
 89     os::jvm_path(jvm_path, sizeof(jvm_path));
 90     char *end = strrchr(jvm_path, *os::file_separator());
 91     if (end != nullptr) *end = '\0';
 92     stringStream tmp;
 93     tmp.print("%s%sclasses", jvm_path, os::file_separator());
 94 #ifdef _LP64
 95     if (!UseCompressedOops) {
 96       tmp.print_raw("_nocoops");
 97     }
 98     if (UseCompactObjectHeaders) {
 99       // Note that generation of xxx_coh.jsa variants require
100       // --enable-cds-archive-coh at build time
101       tmp.print_raw("_coh");
102     }
103 #endif
104     tmp.print_raw(".jsa");
105     _default_archive_path = os::strdup(tmp.base());
106   }
107   return _default_archive_path;
108 }
109 
110 int CDSConfig::num_archives(const char* archive_path) {
111   if (archive_path == nullptr) {
112     return 0;
113   }
114   int npaths = 1;
115   char* p = (char*)archive_path;
116   while (*p != '\0') {
117     if (*p == os::path_separator()[0]) {
118       npaths++;
119     }
120     p++;
121   }
122   return npaths;
123 }
124 
125 void CDSConfig::extract_shared_archive_paths(const char* archive_path,
126                                              char** base_archive_path,
127                                              char** top_archive_path) {
128   char* begin_ptr = (char*)archive_path;
129   char* end_ptr = strchr((char*)archive_path, os::path_separator()[0]);
130   if (end_ptr == nullptr || end_ptr == begin_ptr) {
131     vm_exit_during_initialization("Base archive was not specified", archive_path);
132   }
133   size_t len = end_ptr - begin_ptr;
134   char* cur_path = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal);
135   strncpy(cur_path, begin_ptr, len);
136   cur_path[len] = '\0';
137   *base_archive_path = cur_path;
138 
139   begin_ptr = ++end_ptr;
140   if (*begin_ptr == '\0') {
141     vm_exit_during_initialization("Top archive was not specified", archive_path);
142   }
143   end_ptr = strchr(begin_ptr, '\0');
144   assert(end_ptr != nullptr, "sanity");
145   len = end_ptr - begin_ptr;
146   cur_path = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal);
147   strncpy(cur_path, begin_ptr, len + 1);
148   *top_archive_path = cur_path;
149 }
150 
151 void CDSConfig::init_shared_archive_paths() {
152   if (ArchiveClassesAtExit != nullptr) {
153     assert(!RecordDynamicDumpInfo, "already checked");
154     if (is_dumping_static_archive()) {
155       vm_exit_during_initialization("-XX:ArchiveClassesAtExit cannot be used with -Xshare:dump");
156     }
157     check_unsupported_dumping_module_options();
158 
159     if (os::same_files(default_archive_path(), ArchiveClassesAtExit)) {
160       vm_exit_during_initialization(
161         "Cannot specify the default CDS archive for -XX:ArchiveClassesAtExit", default_archive_path());
162     }
163   }
164 
165   if (SharedArchiveFile == nullptr) {
166     _static_archive_path = default_archive_path();
167   } else {
168     int archives = num_archives(SharedArchiveFile);
169     assert(archives > 0, "must be");
170 
171     if (is_dumping_archive() && archives > 1) {
172       vm_exit_during_initialization(
173         "Cannot have more than 1 archive file specified in -XX:SharedArchiveFile during CDS dumping");
174     }
175 
176     if (is_dumping_static_archive()) {
177       assert(archives == 1, "must be");
178       // Static dump is simple: only one archive is allowed in SharedArchiveFile. This file
179       // will be overwritten no matter regardless of its contents
180       _static_archive_path = os::strdup_check_oom(SharedArchiveFile, mtArguments);
181     } else {
182       // SharedArchiveFile may specify one or two files. In case (c), the path for base.jsa
183       // is read from top.jsa
184       //    (a) 1 file:  -XX:SharedArchiveFile=base.jsa
185       //    (b) 2 files: -XX:SharedArchiveFile=base.jsa:top.jsa
186       //    (c) 2 files: -XX:SharedArchiveFile=top.jsa
187       //
188       // However, if either RecordDynamicDumpInfo or ArchiveClassesAtExit is used, we do not
189       // allow cases (b) and (c). Case (b) is already checked above.
190 
191       if (archives > 2) {
192         vm_exit_during_initialization(
193           "Cannot have more than 2 archive files specified in the -XX:SharedArchiveFile option");
194       }
195       if (archives == 1) {
196         char* base_archive_path = nullptr;
197         bool success =
198           FileMapInfo::get_base_archive_name_from_header(SharedArchiveFile, &base_archive_path);
199         if (!success) {
200           // If +AutoCreateSharedArchive and the specified shared archive does not exist,
201           // regenerate the dynamic archive base on default archive.
202           if (AutoCreateSharedArchive && !os::file_exists(SharedArchiveFile)) {
203             enable_dumping_dynamic_archive();
204             ArchiveClassesAtExit = const_cast<char *>(SharedArchiveFile);
205             _static_archive_path = default_archive_path();
206             SharedArchiveFile = nullptr;
207           } else {
208             if (AutoCreateSharedArchive) {
209               warning("-XX:+AutoCreateSharedArchive is unsupported when base CDS archive is not loaded. Run with -Xlog:cds for more info.");
210               AutoCreateSharedArchive = false;
211             }
212             Arguments::no_shared_spaces("invalid archive");
213           }
214         } else if (base_archive_path == nullptr) {
215           // User has specified a single archive, which is a static archive.
216           _static_archive_path = const_cast<char *>(SharedArchiveFile);
217         } else {
218           // User has specified a single archive, which is a dynamic archive.
219           _dynamic_archive_path = const_cast<char *>(SharedArchiveFile);
220           _static_archive_path = base_archive_path; // has been c-heap allocated.
221         }
222       } else {
223         extract_shared_archive_paths((const char*)SharedArchiveFile,
224                                       &_static_archive_path, &_dynamic_archive_path);
225         if (_static_archive_path == nullptr) {
226           assert(_dynamic_archive_path == nullptr, "must be");
227           Arguments::no_shared_spaces("invalid archive");
228         }
229       }
230 
231       if (_dynamic_archive_path != nullptr) {
232         // Check for case (c)
233         if (RecordDynamicDumpInfo) {
234           vm_exit_during_initialization("-XX:+RecordDynamicDumpInfo is unsupported when a dynamic CDS archive is specified in -XX:SharedArchiveFile",
235                                         SharedArchiveFile);
236         }
237         if (ArchiveClassesAtExit != nullptr) {
238           vm_exit_during_initialization("-XX:ArchiveClassesAtExit is unsupported when a dynamic CDS archive is specified in -XX:SharedArchiveFile",
239                                         SharedArchiveFile);
240         }
241       }
242 
243       if (ArchiveClassesAtExit != nullptr && os::same_files(SharedArchiveFile, ArchiveClassesAtExit)) {
244           vm_exit_during_initialization(
245             "Cannot have the same archive file specified for -XX:SharedArchiveFile and -XX:ArchiveClassesAtExit",
246             SharedArchiveFile);
247       }
248     }
249   }
250 }
251 
252 void CDSConfig::check_internal_module_property(const char* key, const char* value) {
253   if (Arguments::is_internal_module_property(key) &&
254       !Arguments::is_module_path_property(key) &&
255       !Arguments::is_add_modules_property(key)) {
256     stop_using_optimized_module_handling();
257     log_info(cds)("optimized module handling: disabled due to incompatible property: %s=%s", key, value);
258   }
259 }
260 
261 void CDSConfig::check_incompatible_property(const char* key, const char* value) {
262   static const char* incompatible_properties[] = {
263     "java.system.class.loader",
264     "jdk.module.showModuleResolution",
265     "jdk.module.validation"
266   };
267 
268   for (const char* property : incompatible_properties) {
269     if (strcmp(key, property) == 0) {
270       stop_dumping_full_module_graph();
271       stop_using_full_module_graph();
272       log_info(cds)("full module graph: disabled due to incompatible property: %s=%s", key, value);
273       break;
274     }
275   }
276 
277 }
278 
279 // Returns any JVM command-line option, such as "--patch-module", that's not supported by CDS.
280 static const char* find_any_unsupported_module_option() {
281   // Note that arguments.cpp has translated the command-line options into properties. If we find an
282   // unsupported property, translate it back to its command-line option for better error reporting.
283 
284   // The following properties are checked by Arguments::is_internal_module_property() and cannot be
285   // directly specified in the command-line.
286   static const char* unsupported_module_properties[] = {
287     "jdk.module.limitmods",
288     "jdk.module.upgrade.path",
289     "jdk.module.patch.0"
290   };
291   static const char* unsupported_module_options[] = {
292     "--limit-modules",
293     "--upgrade-module-path",
294     "--patch-module"
295   };
296 
297   assert(ARRAY_SIZE(unsupported_module_properties) == ARRAY_SIZE(unsupported_module_options), "must be");
298   SystemProperty* sp = Arguments::system_properties();
299   while (sp != nullptr) {
300     for (uint i = 0; i < ARRAY_SIZE(unsupported_module_properties); i++) {
301       if (strcmp(sp->key(), unsupported_module_properties[i]) == 0) {
302         return unsupported_module_options[i];
303       }
304     }
305     sp = sp->next();
306   }
307 
308   return nullptr; // not found
309 }
310 
311 void CDSConfig::check_unsupported_dumping_module_options() {
312   assert(is_dumping_archive(), "this function is only used with CDS dump time");
313   const char* option = find_any_unsupported_module_option();
314   if (option != nullptr) {
315     vm_exit_during_initialization("Cannot use the following option when dumping the shared archive", option);
316   }
317   // Check for an exploded module build in use with -Xshare:dump.
318   if (!Arguments::has_jimage()) {
319     vm_exit_during_initialization("Dumping the shared archive is not supported with an exploded module build");
320   }
321 }
322 
323 bool CDSConfig::has_unsupported_runtime_module_options() {
324   assert(is_using_archive(), "this function is only used with -Xshare:{on,auto}");
325   if (ArchiveClassesAtExit != nullptr) {
326     // dynamic dumping, just return false for now.
327     // check_unsupported_dumping_properties() will be called later to check the same set of
328     // properties, and will exit the VM with the correct error message if the unsupported properties
329     // are used.
330     return false;
331   }
332   const char* option = find_any_unsupported_module_option();
333   if (option != nullptr) {
334     if (RequireSharedSpaces) {
335       warning("CDS is disabled when the %s option is specified.", option);
336     } else {
337       log_info(cds)("CDS is disabled when the %s option is specified.", option);
338     }
339     return true;
340   }
341   return false;
342 }
343 
344 #define CHECK_ALIAS(f) check_flag_alias(FLAG_IS_DEFAULT(f), #f)
345 
346 void CDSConfig::check_flag_alias(bool alias_is_default, const char* alias_name) {
347   if (_old_cds_flags_used && !alias_is_default) {
348     vm_exit_during_initialization(err_msg("Option %s cannot be used at the same time with "
349                                           "-Xshare:on, -Xshare:auto, -Xshare:off, -Xshare:dump, "
350                                           "DumpLoadedClassList, SharedClassListFile, or SharedArchiveFile",
351                                           alias_name));
352   }
353 }
354 
355 void CDSConfig::check_flag_aliases() {
356   if (!FLAG_IS_DEFAULT(DumpLoadedClassList) ||
357       !FLAG_IS_DEFAULT(SharedClassListFile) ||
358       !FLAG_IS_DEFAULT(SharedArchiveFile)) {
359     _old_cds_flags_used = true;
360   }
361 
362   CHECK_ALIAS(AOTCache);
363   CHECK_ALIAS(AOTConfiguration);
364   CHECK_ALIAS(AOTMode);
365 
366   if (FLAG_IS_DEFAULT(AOTCache) && FLAG_IS_DEFAULT(AOTConfiguration) && FLAG_IS_DEFAULT(AOTMode)) {
367     // Aliases not used.
368     return;
369   }
370 
371   if (FLAG_IS_DEFAULT(AOTMode) || strcmp(AOTMode, "auto") == 0 || strcmp(AOTMode, "on") == 0) {
372     if (!FLAG_IS_DEFAULT(AOTConfiguration)) {
373       vm_exit_during_initialization("AOTConfiguration can only be used with -XX:AOTMode=record or -XX:AOTMode=create");
374     }
375 
376     if (!FLAG_IS_DEFAULT(AOTCache)) {
377       assert(FLAG_IS_DEFAULT(SharedArchiveFile), "already checked");
378       FLAG_SET_ERGO(SharedArchiveFile, AOTCache);
379     }
380 
381     UseSharedSpaces = true;
382     if (FLAG_IS_DEFAULT(AOTMode) || (strcmp(AOTMode, "auto") == 0)) {
383       RequireSharedSpaces = false;
384     } else {
385       assert(strcmp(AOTMode, "on") == 0, "already checked");
386       RequireSharedSpaces = true;
387     }
388   } else if (strcmp(AOTMode, "off") == 0) {
389     UseSharedSpaces = false;
390     RequireSharedSpaces = false;
391   } else {
392     // AOTMode is record or create
393     if (FLAG_IS_DEFAULT(AOTConfiguration)) {
394       vm_exit_during_initialization(err_msg("-XX:AOTMode=%s cannot be used without setting AOTConfiguration", AOTMode));
395     }
396 
397     if (strcmp(AOTMode, "record") == 0) {
398       if (!FLAG_IS_DEFAULT(AOTCache)) {
399         vm_exit_during_initialization("AOTCache must not be specified when using -XX:AOTMode=record");
400       }
401 
402       assert(FLAG_IS_DEFAULT(DumpLoadedClassList), "already checked");
403       FLAG_SET_ERGO(DumpLoadedClassList, AOTConfiguration);
404       UseSharedSpaces = false;
405       RequireSharedSpaces = false;
406     } else {
407       assert(strcmp(AOTMode, "create") == 0, "checked by AOTModeConstraintFunc");
408       if (FLAG_IS_DEFAULT(AOTCache)) {
409         vm_exit_during_initialization("AOTCache must be specified when using -XX:AOTMode=create");
410       }
411 
412       assert(FLAG_IS_DEFAULT(SharedClassListFile), "already checked");
413       FLAG_SET_ERGO(SharedClassListFile, AOTConfiguration);
414       assert(FLAG_IS_DEFAULT(SharedArchiveFile), "already checked");
415       FLAG_SET_ERGO(SharedArchiveFile, AOTCache);
416 
417       CDSConfig::enable_dumping_static_archive();
418     }
419   }
420 }
421 
422 bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_flag_cmd_line) {
423   check_flag_aliases();
424 
425   if (AOTClassLinking) {
426     // If AOTClassLinking is specified, enable all AOT optimizations by default.
427     FLAG_SET_ERGO_IF_DEFAULT(AOTInvokeDynamicLinking, true);
428   } else {
429     // AOTInvokeDynamicLinking depends on AOTClassLinking.
430     FLAG_SET_ERGO(AOTInvokeDynamicLinking, false);
431   }
432 
433   if (is_dumping_static_archive()) {
434     if (!mode_flag_cmd_line) {
435       // By default, -Xshare:dump runs in interpreter-only mode, which is required for deterministic archive.
436       //
437       // If your classlist is large and you don't care about deterministic dumping, you can use
438       // -Xshare:dump -Xmixed to improve dumping speed.
439       Arguments::set_mode_flags(Arguments::_int);
440     } else if (Arguments::mode() == Arguments::_comp) {
441       // -Xcomp may use excessive CPU for the test tiers. Also, -Xshare:dump runs a small and fixed set of
442       // Java code, so there's not much benefit in running -Xcomp.
443       log_info(cds)("reduced -Xcomp to -Xmixed for static dumping");
444       Arguments::set_mode_flags(Arguments::_mixed);
445     }
446 
447     // String deduplication may cause CDS to iterate the strings in different order from one
448     // run to another which resulting in non-determinstic CDS archives.
449     // Disable UseStringDeduplication while dumping CDS archive.
450     UseStringDeduplication = false;
451 
452     // Don't use SoftReferences so that objects used by java.lang.invoke tables can be archived.
453     Arguments::PropertyList_add(new SystemProperty("java.lang.invoke.MethodHandleNatives.USE_SOFT_CACHE", "false", false));
454   }
455 
456   // RecordDynamicDumpInfo is not compatible with ArchiveClassesAtExit
457   if (ArchiveClassesAtExit != nullptr && RecordDynamicDumpInfo) {
458     jio_fprintf(defaultStream::output_stream(),
459                 "-XX:+RecordDynamicDumpInfo cannot be used with -XX:ArchiveClassesAtExit.\n");
460     return false;
461   }
462 
463   if (ArchiveClassesAtExit == nullptr && !RecordDynamicDumpInfo) {
464     disable_dumping_dynamic_archive();
465   } else {
466     enable_dumping_dynamic_archive();
467   }
468 
469   if (AutoCreateSharedArchive) {
470     if (SharedArchiveFile == nullptr) {
471       log_warning(cds)("-XX:+AutoCreateSharedArchive requires -XX:SharedArchiveFile");
472       return false;
473     }
474     if (ArchiveClassesAtExit != nullptr) {
475       log_warning(cds)("-XX:+AutoCreateSharedArchive does not work with ArchiveClassesAtExit");
476       return false;
477     }
478   }
479 
480   if (is_using_archive() && patch_mod_javabase) {
481     Arguments::no_shared_spaces("CDS is disabled when " JAVA_BASE_NAME " module is patched.");
482   }
483   if (is_using_archive() && has_unsupported_runtime_module_options()) {
484     UseSharedSpaces = false;
485   }
486 
487   if (is_dumping_archive()) {
488     // Always verify non-system classes during CDS dump
489     if (!BytecodeVerificationRemote) {
490       BytecodeVerificationRemote = true;
491       log_info(cds)("All non-system classes will be verified (-Xverify:remote) during CDS dump time.");
492     }
493   }
494 
495   return true;
496 }
497 
498 bool CDSConfig::allow_only_single_java_thread() {
499   // See comments in JVM_StartThread()
500   return is_dumping_static_archive();
501 }
502 
503 bool CDSConfig::is_using_archive() {
504   return UseSharedSpaces;
505 }
506 
507 bool CDSConfig::is_logging_lambda_form_invokers() {
508   return ClassListWriter::is_enabled() || is_dumping_dynamic_archive();
509 }
510 
511 void CDSConfig::stop_using_optimized_module_handling() {
512   _is_using_optimized_module_handling = false;
513   _is_dumping_full_module_graph = false; // This requires is_using_optimized_module_handling()
514   _is_using_full_module_graph = false; // This requires is_using_optimized_module_handling()
515 }
516 
517 
518 CDSConfig::DumperThreadMark::DumperThreadMark(JavaThread* current) {
519   assert(_dumper_thread == nullptr, "sanity");
520   _dumper_thread = current;
521 }
522 
523 CDSConfig::DumperThreadMark::~DumperThreadMark() {
524   assert(_dumper_thread != nullptr, "sanity");
525   _dumper_thread = nullptr;
526 }
527 
528 bool CDSConfig::current_thread_is_vm_or_dumper() {
529   Thread* t = Thread::current();
530   return t != nullptr && (t->is_VM_thread() || t == _dumper_thread);
531 }
532 
533 #if INCLUDE_CDS_JAVA_HEAP
534 bool CDSConfig::is_dumping_heap() {
535   // heap dump is not supported in dynamic dump
536   return is_dumping_static_archive() && HeapShared::can_write();
537 }
538 
539 bool CDSConfig::is_loading_heap() {
540   return ArchiveHeapLoader::is_in_use();
541 }
542 
543 bool CDSConfig::is_using_full_module_graph() {
544   if (ClassLoaderDataShared::is_full_module_graph_loaded()) {
545     return true;
546   }
547 
548   if (!_is_using_full_module_graph) {
549     return false;
550   }
551 
552   if (is_using_archive() && ArchiveHeapLoader::can_use()) {
553     // Classes used by the archived full module graph are loaded in JVMTI early phase.
554     assert(!(JvmtiExport::should_post_class_file_load_hook() && JvmtiExport::has_early_class_hook_env()),
555            "CDS should be disabled if early class hooks are enabled");
556     return true;
557   } else {
558     _is_using_full_module_graph = false;
559     return false;
560   }
561 }
562 
563 void CDSConfig::stop_dumping_full_module_graph(const char* reason) {
564   if (_is_dumping_full_module_graph) {
565     _is_dumping_full_module_graph = false;
566     if (reason != nullptr) {
567       log_info(cds)("full module graph cannot be dumped: %s", reason);
568     }
569   }
570 }
571 
572 void CDSConfig::stop_using_full_module_graph(const char* reason) {
573   assert(!ClassLoaderDataShared::is_full_module_graph_loaded(), "you call this function too late!");
574   if (_is_using_full_module_graph) {
575     _is_using_full_module_graph = false;
576     if (reason != nullptr) {
577       log_info(cds)("full module graph cannot be loaded: %s", reason);
578     }
579   }
580 }
581 
582 bool CDSConfig::is_dumping_aot_linked_classes() {
583   if (is_dumping_dynamic_archive()) {
584     return is_using_full_module_graph() && AOTClassLinking;
585   } else if (is_dumping_static_archive()) {
586     return is_dumping_full_module_graph() && AOTClassLinking;
587   } else {
588     return false;
589   }
590 }
591 
592 bool CDSConfig::is_using_aot_linked_classes() {
593   // Make sure we have the exact same module graph as in the assembly phase, or else
594   // some aot-linked classes may not be visible so cannot be loaded.
595   return is_using_full_module_graph() && _has_aot_linked_classes;
596 }
597 
598 void CDSConfig::set_has_aot_linked_classes(bool has_aot_linked_classes) {
599   _has_aot_linked_classes |= has_aot_linked_classes;
600 }
601 
602 bool CDSConfig::is_initing_classes_at_dump_time() {
603   return is_dumping_heap() && is_dumping_aot_linked_classes();
604 }
605 
606 bool CDSConfig::is_dumping_invokedynamic() {
607   // Requires is_dumping_aot_linked_classes(). Otherwise the classes of some archived heap
608   // objects used by the archive indy callsites may be replaced at runtime.
609   return AOTInvokeDynamicLinking && is_dumping_aot_linked_classes() && is_dumping_heap();
610 }
611 
612 bool CDSConfig::is_loading_invokedynamic() {
613   return UseSharedSpaces && is_using_full_module_graph() && _has_archived_invokedynamic;
614 }
615 
616 #endif // INCLUDE_CDS_JAVA_HEAP