diff a/src/hotspot/share/cds/aotMetaspace.cpp b/src/hotspot/share/cds/aotMetaspace.cpp
--- a/src/hotspot/share/cds/aotMetaspace.cpp
+++ b/src/hotspot/share/cds/aotMetaspace.cpp
@@ -21,10 +21,11 @@
  * questions.
  *
  */
 
 #include "cds/aotArtifactFinder.hpp"
+#include "cds/aotCacheAccess.hpp"
 #include "cds/aotClassInitializer.hpp"
 #include "cds/aotClassLinker.hpp"
 #include "cds/aotClassLocation.hpp"
 #include "cds/aotConstantPoolResolver.hpp"
 #include "cds/aotLinkedClassBulkLoader.hpp"
@@ -60,10 +61,12 @@
 #include "classfile/systemDictionaryShared.hpp"
 #include "classfile/vmClasses.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "code/aotCodeCache.hpp"
 #include "code/codeCache.hpp"
+#include "compiler/compileBroker.hpp"
+#include "compiler/precompiler.hpp"
 #include "gc/shared/gcVMOperations.hpp"
 #include "interpreter/bytecodes.hpp"
 #include "interpreter/bytecodeStream.hpp"
 #include "jvm_io.h"
 #include "logging/log.hpp"
@@ -77,15 +80,17 @@
 #include "memory/universe.hpp"
 #include "nmt/memTracker.hpp"
 #include "oops/compressedKlass.hpp"
 #include "oops/instanceMirrorKlass.hpp"
 #include "oops/klass.inline.hpp"
+#include "oops/method.inline.hpp"
 #include "oops/objArrayOop.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/oopHandle.hpp"
 #include "oops/trainingData.hpp"
 #include "prims/jvmtiExport.hpp"
+#include "prims/whitebox.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/globals.hpp"
 #include "runtime/globals_extension.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/javaCalls.hpp"
@@ -93,10 +98,11 @@
 #include "runtime/safepointVerifiers.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/vmOperations.hpp"
 #include "runtime/vmThread.hpp"
 #include "sanitizers/leak.hpp"
+#include "services/management.hpp"
 #include "utilities/align.hpp"
 #include "utilities/bitMap.inline.hpp"
 #include "utilities/defaultStream.hpp"
 #include "utilities/hashTable.hpp"
 #include "utilities/macros.hpp"
@@ -111,10 +117,12 @@
 void* AOTMetaspace::_aot_metaspace_static_top = nullptr;
 intx AOTMetaspace::_relocation_delta;
 char* AOTMetaspace::_requested_base_address;
 Array<Method*>* AOTMetaspace::_archived_method_handle_intrinsics = nullptr;
 bool AOTMetaspace::_use_optimized_module_handling = true;
+int volatile AOTMetaspace::_preimage_static_archive_dumped = 0;
+jlong AOTMetaspace::_preimage_static_archive_recording_duration = 0;
 
 // The CDS archive is divided into the following regions:
 //     rw  - read-write metadata
 //     ro  - read-only metadata and read-only tables
 //     hp  - heap region
@@ -291,10 +299,25 @@
   return aligned_base;
 }
 
 void AOTMetaspace::initialize_for_static_dump() {
   assert(CDSConfig::is_dumping_static_archive(), "sanity");
+
+  if (CDSConfig::is_dumping_preimage_static_archive() || CDSConfig::is_dumping_final_static_archive()) {
+    if (!((UseG1GC || UseParallelGC || UseSerialGC || UseEpsilonGC || UseShenandoahGC) && UseCompressedClassPointers)) {
+      const char* error;
+      if (CDSConfig::is_dumping_preimage_static_archive()) {
+        error = "Cannot create the AOT configuration file";
+      } else {
+        error = "Cannot create the AOT cache";
+      }
+
+      vm_exit_during_initialization(error,
+                                    "UseCompressedClassPointers must be enabled, and collector must be G1, Parallel, Serial, Epsilon, or Shenandoah");
+    }
+  }
+
   aot_log_info(aot)("Core region alignment: %zu", core_region_alignment());
   // The max allowed size for CDS archive. We use this to limit SharedBaseAddress
   // to avoid address space wrap around.
   size_t cds_max;
   const size_t reserve_alignment = core_region_alignment();
@@ -715,10 +738,12 @@
   _map_info->populate_header(AOTMetaspace::core_region_alignment());
   _map_info->set_early_serialized_data(early_serialized_data);
   _map_info->set_serialized_data(serialized_data);
   _map_info->set_cloned_vtables(CppVtables::vtables_serialized_base());
   _map_info->header()->set_class_location_config(cl_config);
+
+  HeapShared::delete_tables_with_raw_oops();
 }
 
 class CollectClassesForLinking : public KlassClosure {
   GrowableArray<OopHandle> _mirrors;
 
@@ -753,10 +778,13 @@
 };
 
 // Check if we can eagerly link this class at dump time, so we can avoid the
 // runtime linking overhead (especially verification)
 bool AOTMetaspace::may_be_eagerly_linked(InstanceKlass* ik) {
+  if (CDSConfig::preserve_all_dumptime_verification_states(ik)) {
+    assert(ik->can_be_verified_at_dumptime(), "sanity");
+  }
   if (!ik->can_be_verified_at_dumptime()) {
     // For old classes, try to leave them in the unlinked state, so
     // we can still store them in the archive. They must be
     // linked/verified at runtime.
     return false;
@@ -775,10 +803,14 @@
 
 void AOTMetaspace::link_shared_classes(TRAPS) {
   AOTClassLinker::initialize();
   AOTClassInitializer::init_test_class(CHECK);
 
+  if (CDSConfig::is_dumping_final_static_archive()) {
+    FinalImageRecipes::apply_recipes(CHECK);
+  }
+
   while (true) {
     ResourceMark rm(THREAD);
     CollectClassesForLinking collect_classes;
     bool has_linked = false;
     const GrowableArray<OopHandle>* mirrors = collect_classes.mirrors();
@@ -786,10 +818,13 @@
       OopHandle mirror = mirrors->at(i);
       InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(mirror.resolve()));
       if (may_be_eagerly_linked(ik)) {
         has_linked |= try_link_class(THREAD, ik);
       }
+      if (CDSConfig::is_dumping_heap() && ik->is_linked() && !ik->is_initialized()) {
+        AOTClassInitializer::maybe_preinit_class(ik, CHECK);
+      }
     }
 
     if (!has_linked) {
       break;
     }
@@ -804,29 +839,28 @@
     const GrowableArray<OopHandle>* mirrors = collect_classes.mirrors();
     for (int i = 0; i < mirrors->length(); i++) {
       OopHandle mirror = mirrors->at(i);
       InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(mirror.resolve()));
       AOTConstantPoolResolver::preresolve_string_cp_entries(ik, CHECK);
+      if (CDSConfig::is_dumping_preimage_static_archive()) {
+        FinalImageRecipes::add_reflection_data_flags(ik, CHECK);
+      }
     }
   }
-
-  if (CDSConfig::is_dumping_final_static_archive()) {
-    FinalImageRecipes::apply_recipes(CHECK);
-  }
 }
 
 // Preload classes from a list, populate the shared spaces and dump to a
 // file.
 void AOTMetaspace::preload_and_dump(TRAPS) {
   CDSConfig::DumperThreadMark dumper_thread_mark(THREAD);
   ResourceMark rm(THREAD);
- HandleMark hm(THREAD);
+  HandleMark hm(THREAD);
 
- if (CDSConfig::is_dumping_final_static_archive() && AOTPrintTrainingInfo) {
-   tty->print_cr("==================== archived_training_data ** before dumping ====================");
-   TrainingData::print_archived_training_data_on(tty);
- }
+  if (CDSConfig::is_dumping_final_static_archive() && AOTPrintTrainingInfo) {
+    tty->print_cr("==================== archived_training_data ** before dumping ====================");
+    TrainingData::print_archived_training_data_on(tty);
+  }
 
   StaticArchiveBuilder builder;
   preload_and_dump_impl(builder, THREAD);
   if (HAS_PENDING_EXCEPTION) {
     if (PENDING_EXCEPTION->is_a(vmClasses::OutOfMemoryError_klass())) {
@@ -935,11 +969,36 @@
 
   // Exercise FileSystem and URL code
   CDSProtectionDomain::to_file_URL("dummy.jar", Handle(), CHECK);
 }
 
+bool AOTMetaspace::is_recording_preimage_static_archive() {
+  if (CDSConfig::is_dumping_preimage_static_archive()) {
+      return _preimage_static_archive_dumped == 0;
+  }
+  return false;
+}
+
+jlong AOTMetaspace::get_preimage_static_archive_recording_duration() {
+  if (CDSConfig::is_dumping_preimage_static_archive()) {
+    if (_preimage_static_archive_recording_duration == 0) {
+      // The recording has not yet finished so return the current elapsed time.
+      return Management::ticks_to_ms(os::elapsed_counter());
+    }
+    return _preimage_static_archive_recording_duration;
+  }
+  return 0;
+}
+
 void AOTMetaspace::preload_and_dump_impl(StaticArchiveBuilder& builder, TRAPS) {
+  if (CDSConfig::is_dumping_preimage_static_archive()) {
+    if (Atomic::cmpxchg(&_preimage_static_archive_dumped, 0, 1) != 0) {
+      return;
+    }
+    _preimage_static_archive_recording_duration = Management::ticks_to_ms(os::elapsed_counter());
+  }
+
   if (CDSConfig::is_dumping_classic_static_archive()) {
     // We are running with -Xshare:dump
     preload_classes(CHECK);
 
     if (SharedArchiveConfigFile) {
@@ -1002,10 +1061,14 @@
     if (CDSConfig::is_dumping_full_module_graph()) {
       ClassLoaderDataShared::ensure_module_entry_tables_exist();
       HeapShared::reset_archived_object_states(CHECK);
     }
 
+    if (ArchiveLoaderLookupCache) {
+      SystemDictionaryShared::create_loader_positive_lookup_cache(CHECK);
+    }
+
     AOTReferenceObjSupport::initialize(CHECK);
     AOTReferenceObjSupport::stabilize_cached_reference_objects(CHECK);
 
     if (CDSConfig::is_initing_classes_at_dump_time()) {
       // java.lang.Class::reflectionFactory cannot be archived yet. We set this field
@@ -1030,23 +1093,43 @@
   }
 #endif
 
   VM_PopulateDumpSharedSpace op(builder);
   VMThread::execute(&op);
+  FileMapInfo* mapinfo = op.map_info();
+  ArchiveHeapInfo* heap_info = op.heap_info();
+
+  if (CDSConfig::is_dumping_final_static_archive()) {
+    if (AOTCodeCache::is_caching_enabled()) {
+      if (log_is_enabled(Info, cds, jit)) {
+        AOTCacheAccess::test_heap_access_api();
+      }
+
+      // We have just created the final image. Let's run the AOT compiler
+      if (AOTPrintTrainingInfo) {
+        tty->print_cr("==================== archived_training_data ** after dumping ====================");
+        TrainingData::print_archived_training_data_on(tty);
+      }
 
-  if (AOTCodeCache::is_on_for_dump() && CDSConfig::is_dumping_final_static_archive()) {
-    CDSConfig::enable_dumping_aot_code();
-    {
-      builder.start_ac_region();
-      // Write the contents to AOT code region and close AOTCodeCache before packing the region
-      AOTCodeCache::close();
-      builder.end_ac_region();
+      {
+        builder.start_ac_region();
+        if (AOTCodeCache::is_dumping_code()) {
+          CDSConfig::enable_dumping_aot_code();
+          log_info(aot)("Compiling AOT code");
+          Precompiler::compile_aot_code(&builder, CHECK);
+          log_info(aot)("Finished compiling AOT code");
+          CDSConfig::disable_dumping_aot_code();
+        }
+        // Write the contents to aot code region and close AOTCodeCache before packing the region
+        AOTCodeCache::close();
+        log_info(aot)("Dumped AOT code Cache");
+        builder.end_ac_region();
+      }
     }
-    CDSConfig::disable_dumping_aot_code();
   }
 
-  bool status = write_static_archive(&builder, op.map_info(), op.heap_info());
+  bool status = write_static_archive(&builder, mapinfo, heap_info);
   if (status && CDSConfig::is_dumping_preimage_static_archive()) {
     tty->print_cr("%s AOTConfiguration recorded: %s",
                   CDSConfig::has_temp_aot_config_file() ? "Temporary" : "", AOTConfiguration);
     if (CDSConfig::is_single_command_training()) {
       fork_and_dump_final_static_archive(CHECK);
@@ -1245,11 +1328,11 @@
 }
 
 void VM_PopulateDumpSharedSpace::dump_java_heap_objects() {
   if (CDSConfig::is_dumping_heap()) {
     HeapShared::write_heap(&_heap_info);
-  } else {
+  } else if (!CDSConfig::is_dumping_preimage_static_archive()) {
     CDSConfig::log_reasons_for_not_dumping_heap();
   }
 }
 
 void AOTMetaspace::set_aot_metaspace_range(void* base, void *static_top, void* top) {
@@ -1341,11 +1424,11 @@
 
 void AOTMetaspace::initialize_runtime_shared_and_meta_spaces() {
   assert(CDSConfig::is_using_archive(), "Must be called when UseSharedSpaces is enabled");
   MapArchiveResult result = MAP_ARCHIVE_OTHER_FAILURE;
 
-  FileMapInfo* static_mapinfo = open_static_archive();
+  FileMapInfo* static_mapinfo = FileMapInfo::current_info();
   FileMapInfo* dynamic_mapinfo = nullptr;
 
   if (static_mapinfo != nullptr) {
     aot_log_info(aot)("Core region alignment: %zu", static_mapinfo->core_region_alignment());
     dynamic_mapinfo = open_dynamic_archive();
@@ -1404,23 +1487,29 @@
   if (dynamic_mapinfo != nullptr && !dynamic_mapinfo->is_mapped()) {
     has_failed = true;
     delete dynamic_mapinfo;
   }
   if (RequireSharedSpaces && has_failed) {
+    // static archive mapped but dynamic archive failed
       AOTMetaspace::unrecoverable_loading_error("Unable to map shared spaces");
   }
 }
 
-FileMapInfo* AOTMetaspace::open_static_archive() {
+// This is called very early at VM start up to get the size of the cached_code region
+void AOTMetaspace::open_static_archive() {
+  if (!UseSharedSpaces) { // FIXME -- is this still needed??
+    return;
+  }
   const char* static_archive = CDSConfig::input_static_archive_path();
   assert(static_archive != nullptr, "sanity");
   FileMapInfo* mapinfo = new FileMapInfo(static_archive, true);
   if (!mapinfo->open_as_input()) {
     delete(mapinfo);
-    return nullptr;
+  } else {
+    FileMapRegion* r = mapinfo->region_at(AOTMetaspace::ac);
+    AOTCacheAccess::set_aot_code_region_size(r->used_aligned());
   }
-  return mapinfo;
 }
 
 FileMapInfo* AOTMetaspace::open_dynamic_archive() {
   if (CDSConfig::is_dumping_dynamic_archive()) {
     return nullptr;
@@ -1907,10 +1996,14 @@
   assert(CDSConfig::is_using_archive(), "must be runtime");
   if (mapinfo == nullptr) {
     return MAP_ARCHIVE_SUCCESS; // The dynamic archive has not been specified. No error has happened -- trivially succeeded.
   }
 
+  if (!mapinfo->validate_aot_class_linking()) {
+    return MAP_ARCHIVE_OTHER_FAILURE;
+  }
+
   mapinfo->set_is_mapped(false);
   if (mapinfo->core_region_alignment() != (size_t)core_region_alignment()) {
     report_loading_error("Unable to map CDS archive -- core_region_alignment() expected: %zu"
                          " actual: %zu", mapinfo->core_region_alignment(), core_region_alignment());
     return MAP_ARCHIVE_OTHER_FAILURE;
