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_incompatible_cds_internal_module_property(key)) {
254     stop_using_optimized_module_handling();
255     log_info(cds)("optimized module handling: disabled due to incompatible property: %s=%s", key, value);
256   }
257 }
258 
259 void CDSConfig::check_incompatible_property(const char* key, const char* value) {
260   static const char* incompatible_properties[] = {
261     "java.system.class.loader",
262     "jdk.module.showModuleResolution",
263     "jdk.module.validation"
264   };
265 
266   for (const char* property : incompatible_properties) {
267     if (strcmp(key, property) == 0) {
268       stop_dumping_full_module_graph();
269       stop_using_full_module_graph();
270       log_info(cds)("full module graph: disabled due to incompatible property: %s=%s", key, value);
271       break;
272     }
273   }
274 
275 }
276 
277 // Returns any JVM command-line option, such as "--patch-module", that's not supported by CDS.
278 static const char* find_any_unsupported_module_option() {
279   // Note that arguments.cpp has translated the command-line options into properties. If we find an
280   // unsupported property, translate it back to its command-line option for better error reporting.
281 
282   // The following properties are checked by Arguments::is_internal_module_property() and cannot be
283   // directly specified in the command-line.
284   static const char* unsupported_module_properties[] = {
285     "jdk.module.limitmods",
286     "jdk.module.upgrade.path",
287     "jdk.module.patch.0"
288   };
289   static const char* unsupported_module_options[] = {
290     "--limit-modules",
291     "--upgrade-module-path",
292     "--patch-module"
293   };
294 
295   assert(ARRAY_SIZE(unsupported_module_properties) == ARRAY_SIZE(unsupported_module_options), "must be");
296   SystemProperty* sp = Arguments::system_properties();
297   while (sp != nullptr) {
298     for (uint i = 0; i < ARRAY_SIZE(unsupported_module_properties); i++) {
299       if (strcmp(sp->key(), unsupported_module_properties[i]) == 0) {
300         return unsupported_module_options[i];
301       }
302     }
303     sp = sp->next();
304   }
305 
306   return nullptr; // not found
307 }
308 
309 void CDSConfig::check_unsupported_dumping_module_options() {
310   assert(is_dumping_archive(), "this function is only used with CDS dump time");
311   const char* option = find_any_unsupported_module_option();
312   if (option != nullptr) {
313     vm_exit_during_initialization("Cannot use the following option when dumping the shared archive", option);
314   }
315   // Check for an exploded module build in use with -Xshare:dump.
316   if (!Arguments::has_jimage()) {
317     vm_exit_during_initialization("Dumping the shared archive is not supported with an exploded module build");
318   }
319 }
320 
321 bool CDSConfig::has_unsupported_runtime_module_options() {
322   assert(is_using_archive(), "this function is only used with -Xshare:{on,auto}");
323   if (ArchiveClassesAtExit != nullptr) {
324     // dynamic dumping, just return false for now.
325     // check_unsupported_dumping_properties() will be called later to check the same set of
326     // properties, and will exit the VM with the correct error message if the unsupported properties
327     // are used.
328     return false;
329   }
330   const char* option = find_any_unsupported_module_option();
331   if (option != nullptr) {
332     if (RequireSharedSpaces) {
333       warning("CDS is disabled when the %s option is specified.", option);
334     } else {
335       log_info(cds)("CDS is disabled when the %s option is specified.", option);
336     }
337     return true;
338   }
339   return false;
340 }
341 
342 #define CHECK_ALIAS(f) check_flag_alias(FLAG_IS_DEFAULT(f), #f)
343 
344 void CDSConfig::check_flag_alias(bool alias_is_default, const char* alias_name) {
345   if (_old_cds_flags_used && !alias_is_default) {
346     vm_exit_during_initialization(err_msg("Option %s cannot be used at the same time with "
347                                           "-Xshare:on, -Xshare:auto, -Xshare:off, -Xshare:dump, "
348                                           "DumpLoadedClassList, SharedClassListFile, or SharedArchiveFile",
349                                           alias_name));
350   }
351 }
352 
353 void CDSConfig::check_flag_aliases() {
354   if (!FLAG_IS_DEFAULT(DumpLoadedClassList) ||
355       !FLAG_IS_DEFAULT(SharedClassListFile) ||
356       !FLAG_IS_DEFAULT(SharedArchiveFile)) {
357     _old_cds_flags_used = true;
358   }
359 
360   CHECK_ALIAS(AOTCache);
361   CHECK_ALIAS(AOTConfiguration);
362   CHECK_ALIAS(AOTMode);
363 
364   if (FLAG_IS_DEFAULT(AOTCache) && FLAG_IS_DEFAULT(AOTConfiguration) && FLAG_IS_DEFAULT(AOTMode)) {
365     // Aliases not used.
366     return;
367   }
368 
369   if (FLAG_IS_DEFAULT(AOTMode) || strcmp(AOTMode, "auto") == 0 || strcmp(AOTMode, "on") == 0) {
370     if (!FLAG_IS_DEFAULT(AOTConfiguration)) {
371       vm_exit_during_initialization("AOTConfiguration can only be used with -XX:AOTMode=record or -XX:AOTMode=create");
372     }
373 
374     if (!FLAG_IS_DEFAULT(AOTCache)) {
375       assert(FLAG_IS_DEFAULT(SharedArchiveFile), "already checked");
376       FLAG_SET_ERGO(SharedArchiveFile, AOTCache);
377     }
378 
379     UseSharedSpaces = true;
380     if (FLAG_IS_DEFAULT(AOTMode) || (strcmp(AOTMode, "auto") == 0)) {
381       RequireSharedSpaces = false;
382     } else {
383       assert(strcmp(AOTMode, "on") == 0, "already checked");
384       RequireSharedSpaces = true;
385     }
386   } else if (strcmp(AOTMode, "off") == 0) {
387     UseSharedSpaces = false;
388     RequireSharedSpaces = false;
389   } else {
390     // AOTMode is record or create
391     if (FLAG_IS_DEFAULT(AOTConfiguration)) {
392       vm_exit_during_initialization(err_msg("-XX:AOTMode=%s cannot be used without setting AOTConfiguration", AOTMode));
393     }
394 
395     if (strcmp(AOTMode, "record") == 0) {
396       if (!FLAG_IS_DEFAULT(AOTCache)) {
397         vm_exit_during_initialization("AOTCache must not be specified when using -XX:AOTMode=record");
398       }
399 
400       assert(FLAG_IS_DEFAULT(DumpLoadedClassList), "already checked");
401       FLAG_SET_ERGO(DumpLoadedClassList, AOTConfiguration);
402       UseSharedSpaces = false;
403       RequireSharedSpaces = false;
404     } else {
405       assert(strcmp(AOTMode, "create") == 0, "checked by AOTModeConstraintFunc");
406       if (FLAG_IS_DEFAULT(AOTCache)) {
407         vm_exit_during_initialization("AOTCache must be specified when using -XX:AOTMode=create");
408       }
409 
410       assert(FLAG_IS_DEFAULT(SharedClassListFile), "already checked");
411       FLAG_SET_ERGO(SharedClassListFile, AOTConfiguration);
412       assert(FLAG_IS_DEFAULT(SharedArchiveFile), "already checked");
413       FLAG_SET_ERGO(SharedArchiveFile, AOTCache);
414 
415       CDSConfig::enable_dumping_static_archive();
416     }
417   }
418 }
419 
420 bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_flag_cmd_line) {
421   check_flag_aliases();
422 
423   if (AOTClassLinking) {
424     // If AOTClassLinking is specified, enable all AOT optimizations by default.
425     FLAG_SET_ERGO_IF_DEFAULT(AOTInvokeDynamicLinking, true);
426   } else {
427     // AOTInvokeDynamicLinking depends on AOTClassLinking.
428     FLAG_SET_ERGO(AOTInvokeDynamicLinking, false);
429   }
430 
431   if (is_dumping_static_archive()) {
432     if (!mode_flag_cmd_line) {
433       // By default, -Xshare:dump runs in interpreter-only mode, which is required for deterministic archive.
434       //
435       // If your classlist is large and you don't care about deterministic dumping, you can use
436       // -Xshare:dump -Xmixed to improve dumping speed.
437       Arguments::set_mode_flags(Arguments::_int);
438     } else if (Arguments::mode() == Arguments::_comp) {
439       // -Xcomp may use excessive CPU for the test tiers. Also, -Xshare:dump runs a small and fixed set of
440       // Java code, so there's not much benefit in running -Xcomp.
441       log_info(cds)("reduced -Xcomp to -Xmixed for static dumping");
442       Arguments::set_mode_flags(Arguments::_mixed);
443     }
444 
445     // String deduplication may cause CDS to iterate the strings in different order from one
446     // run to another which resulting in non-determinstic CDS archives.
447     // Disable UseStringDeduplication while dumping CDS archive.
448     UseStringDeduplication = false;
449 
450     // Don't use SoftReferences so that objects used by java.lang.invoke tables can be archived.
451     Arguments::PropertyList_add(new SystemProperty("java.lang.invoke.MethodHandleNatives.USE_SOFT_CACHE", "false", false));
452   }
453 
454   // RecordDynamicDumpInfo is not compatible with ArchiveClassesAtExit
455   if (ArchiveClassesAtExit != nullptr && RecordDynamicDumpInfo) {
456     jio_fprintf(defaultStream::output_stream(),
457                 "-XX:+RecordDynamicDumpInfo cannot be used with -XX:ArchiveClassesAtExit.\n");
458     return false;
459   }
460 
461   if (ArchiveClassesAtExit == nullptr && !RecordDynamicDumpInfo) {
462     disable_dumping_dynamic_archive();
463   } else {
464     enable_dumping_dynamic_archive();
465   }
466 
467   if (AutoCreateSharedArchive) {
468     if (SharedArchiveFile == nullptr) {
469       log_warning(cds)("-XX:+AutoCreateSharedArchive requires -XX:SharedArchiveFile");
470       return false;
471     }
472     if (ArchiveClassesAtExit != nullptr) {
473       log_warning(cds)("-XX:+AutoCreateSharedArchive does not work with ArchiveClassesAtExit");
474       return false;
475     }
476   }
477 
478   if (is_using_archive() && patch_mod_javabase) {
479     Arguments::no_shared_spaces("CDS is disabled when " JAVA_BASE_NAME " module is patched.");
480   }
481   if (is_using_archive() && has_unsupported_runtime_module_options()) {
482     UseSharedSpaces = false;
483   }
484 
485   if (is_dumping_archive()) {
486     // Always verify non-system classes during CDS dump
487     if (!BytecodeVerificationRemote) {
488       BytecodeVerificationRemote = true;
489       log_info(cds)("All non-system classes will be verified (-Xverify:remote) during CDS dump time.");
490     }
491   }
492 
493   return true;
494 }
495 
496 bool CDSConfig::allow_only_single_java_thread() {
497   // See comments in JVM_StartThread()
498   return is_dumping_static_archive();
499 }
500 
501 bool CDSConfig::is_using_archive() {
502   return UseSharedSpaces;
503 }
504 
505 bool CDSConfig::is_logging_lambda_form_invokers() {
506   return ClassListWriter::is_enabled() || is_dumping_dynamic_archive();
507 }
508 
509 void CDSConfig::stop_using_optimized_module_handling() {
510   _is_using_optimized_module_handling = false;
511   _is_dumping_full_module_graph = false; // This requires is_using_optimized_module_handling()
512   _is_using_full_module_graph = false; // This requires is_using_optimized_module_handling()
513 }
514 
515 
516 CDSConfig::DumperThreadMark::DumperThreadMark(JavaThread* current) {
517   assert(_dumper_thread == nullptr, "sanity");
518   _dumper_thread = current;
519 }
520 
521 CDSConfig::DumperThreadMark::~DumperThreadMark() {
522   assert(_dumper_thread != nullptr, "sanity");
523   _dumper_thread = nullptr;
524 }
525 
526 bool CDSConfig::current_thread_is_vm_or_dumper() {
527   Thread* t = Thread::current();
528   return t != nullptr && (t->is_VM_thread() || t == _dumper_thread);
529 }
530 
531 #if INCLUDE_CDS_JAVA_HEAP
532 bool CDSConfig::is_dumping_heap() {
533   // heap dump is not supported in dynamic dump
534   return is_dumping_static_archive() && HeapShared::can_write();
535 }
536 
537 bool CDSConfig::is_loading_heap() {
538   return ArchiveHeapLoader::is_in_use();
539 }
540 
541 bool CDSConfig::is_using_full_module_graph() {
542   if (ClassLoaderDataShared::is_full_module_graph_loaded()) {
543     return true;
544   }
545 
546   if (!_is_using_full_module_graph) {
547     return false;
548   }
549 
550   if (is_using_archive() && ArchiveHeapLoader::can_use()) {
551     // Classes used by the archived full module graph are loaded in JVMTI early phase.
552     assert(!(JvmtiExport::should_post_class_file_load_hook() && JvmtiExport::has_early_class_hook_env()),
553            "CDS should be disabled if early class hooks are enabled");
554     return true;
555   } else {
556     _is_using_full_module_graph = false;
557     return false;
558   }
559 }
560 
561 void CDSConfig::stop_dumping_full_module_graph(const char* reason) {
562   if (_is_dumping_full_module_graph) {
563     _is_dumping_full_module_graph = false;
564     if (reason != nullptr) {
565       log_info(cds)("full module graph cannot be dumped: %s", reason);
566     }
567   }
568 }
569 
570 void CDSConfig::stop_using_full_module_graph(const char* reason) {
571   assert(!ClassLoaderDataShared::is_full_module_graph_loaded(), "you call this function too late!");
572   if (_is_using_full_module_graph) {
573     _is_using_full_module_graph = false;
574     if (reason != nullptr) {
575       log_info(cds)("full module graph cannot be loaded: %s", reason);
576     }
577   }
578 }
579 
580 bool CDSConfig::is_dumping_aot_linked_classes() {
581   if (is_dumping_dynamic_archive()) {
582     return is_using_full_module_graph() && AOTClassLinking;
583   } else if (is_dumping_static_archive()) {
584     return is_dumping_full_module_graph() && AOTClassLinking;
585   } else {
586     return false;
587   }
588 }
589 
590 bool CDSConfig::is_using_aot_linked_classes() {
591   // Make sure we have the exact same module graph as in the assembly phase, or else
592   // some aot-linked classes may not be visible so cannot be loaded.
593   return is_using_full_module_graph() && _has_aot_linked_classes;
594 }
595 
596 void CDSConfig::set_has_aot_linked_classes(bool has_aot_linked_classes) {
597   _has_aot_linked_classes |= has_aot_linked_classes;
598 }
599 
600 bool CDSConfig::is_initing_classes_at_dump_time() {
601   return is_dumping_heap() && is_dumping_aot_linked_classes();
602 }
603 
604 bool CDSConfig::is_dumping_invokedynamic() {
605   // Requires is_dumping_aot_linked_classes(). Otherwise the classes of some archived heap
606   // objects used by the archive indy callsites may be replaced at runtime.
607   return AOTInvokeDynamicLinking && is_dumping_aot_linked_classes() && is_dumping_heap();
608 }
609 
610 bool CDSConfig::is_loading_invokedynamic() {
611   return UseSharedSpaces && is_using_full_module_graph() && _has_archived_invokedynamic;
612 }
613 
614 #endif // INCLUDE_CDS_JAVA_HEAP