diff a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp
--- a/src/hotspot/share/oops/cpCache.cpp
+++ b/src/hotspot/share/oops/cpCache.cpp
@@ -21,13 +21,13 @@
  * questions.
  *
  */
 
 #include "precompiled.hpp"
+#include "cds/aotConstantPoolResolver.hpp"
 #include "cds/archiveBuilder.hpp"
 #include "cds/cdsConfig.hpp"
-#include "cds/classPrelinker.hpp"
 #include "cds/heapShared.hpp"
 #include "classfile/resolutionErrors.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/systemDictionaryShared.hpp"
 #include "classfile/vmClasses.hpp"
@@ -47,10 +47,11 @@
 #include "oops/constantPool.inline.hpp"
 #include "oops/cpCache.inline.hpp"
 #include "oops/method.inline.hpp"
 #include "oops/objArrayOop.inline.hpp"
 #include "oops/oop.inline.hpp"
+#include "oops/method.inline.hpp"
 #include "oops/resolvedFieldEntry.hpp"
 #include "oops/resolvedIndyEntry.hpp"
 #include "oops/resolvedMethodEntry.hpp"
 #include "prims/methodHandles.hpp"
 #include "runtime/arguments.hpp"
@@ -174,11 +175,12 @@
         method->name() != vmSymbols::object_initializer_name()) {
       do_resolve = false;
     }
     if (invoke_code == Bytecodes::_invokestatic) {
       assert(method->method_holder()->is_initialized() ||
-             method->method_holder()->is_reentrant_initialization(JavaThread::current()),
+             method->method_holder()->is_reentrant_initialization(JavaThread::current()) ||
+             (CDSConfig::is_dumping_archive() && VM_Version::supports_fast_class_init_checks()),
              "invalid class initialization state for invoke_static");
 
       if (!VM_Version::supports_fast_class_init_checks() && method->needs_clinit_barrier()) {
         // Don't mark invokestatic to method as resolved if the holder class has not yet completed
         // initialization. An invokestatic must only proceed if the class is initialized, but if
@@ -399,13 +401,11 @@
 #if INCLUDE_CDS
 void ConstantPoolCache::remove_unshareable_info() {
   assert(CDSConfig::is_dumping_archive(), "sanity");
 
   if (_resolved_indy_entries != nullptr) {
-    for (int i = 0; i < _resolved_indy_entries->length(); i++) {
-      resolved_indy_entry_at(i)->remove_unshareable_info();
-    }
+    remove_resolved_indy_entries_if_non_deterministic();
   }
   if (_resolved_field_entries != nullptr) {
     remove_resolved_field_entries_if_non_deterministic();
   }
   if (_resolved_method_entries != nullptr) {
@@ -418,13 +418,15 @@
   ConstantPool* src_cp =  ArchiveBuilder::current()->get_source_addr(cp);
   for (int i = 0; i < _resolved_field_entries->length(); i++) {
     ResolvedFieldEntry* rfi = _resolved_field_entries->adr_at(i);
     int cp_index = rfi->constant_pool_index();
     bool archived = false;
-    bool resolved = rfi->is_resolved(Bytecodes::_getfield)  ||
+    bool resolved = rfi->is_resolved(Bytecodes::_getstatic) ||
+                    rfi->is_resolved(Bytecodes::_putstatic) ||
+                    rfi->is_resolved(Bytecodes::_getfield)  ||
                     rfi->is_resolved(Bytecodes::_putfield);
-    if (resolved && ClassPrelinker::is_resolution_deterministic(src_cp, cp_index)) {
+    if (resolved && AOTConstantPoolResolver::is_resolution_deterministic(src_cp, cp_index)) {
       rfi->mark_and_relocate();
       archived = true;
     } else {
       rfi->remove_unshareable_info();
     }
@@ -434,15 +436,14 @@
         ResourceMark rm;
         int klass_cp_index = cp->uncached_klass_ref_index_at(cp_index);
         Symbol* klass_name = cp->klass_name_at(klass_cp_index);
         Symbol* name = cp->uncached_name_ref_at(cp_index);
         Symbol* signature = cp->uncached_signature_ref_at(cp_index);
-        log.print("%s field  CP entry [%3d]: %s %s %s.%s:%s",
+        log.print("%s field  CP entry [%3d]: %s => %s.%s:%s",
                   (archived ? "archived" : "reverted"),
                   cp_index,
                   cp->pool_holder()->name()->as_C_string(),
-                  (archived ? "=>" : "  "),
                   klass_name->as_C_string(), name->as_C_string(), signature->as_C_string());
       }
     }
     ArchiveBuilder::alloc_stats()->record_field_cp_entry(archived, resolved && !archived);
   }
@@ -455,17 +456,14 @@
     ResolvedMethodEntry* rme = _resolved_method_entries->adr_at(i);
     int cp_index = rme->constant_pool_index();
     bool archived = false;
     bool resolved = rme->is_resolved(Bytecodes::_invokevirtual)   ||
                     rme->is_resolved(Bytecodes::_invokespecial)   ||
-                    rme->is_resolved(Bytecodes::_invokeinterface);
-
-    // Just for safety -- this should not happen, but do not archive if we ever see this.
-    resolved &= !(rme->is_resolved(Bytecodes::_invokehandle) ||
-                  rme->is_resolved(Bytecodes::_invokestatic));
-
-    if (resolved && can_archive_resolved_method(rme)) {
+                    rme->is_resolved(Bytecodes::_invokestatic)    ||
+                    rme->is_resolved(Bytecodes::_invokeinterface) ||
+                    rme->is_resolved(Bytecodes::_invokehandle);
+    if (resolved && can_archive_resolved_method(src_cp, rme)) {
       rme->mark_and_relocate(src_cp);
       archived = true;
     } else {
       rme->remove_unshareable_info();
     }
@@ -493,11 +491,61 @@
       ArchiveBuilder::alloc_stats()->record_method_cp_entry(archived, resolved && !archived);
     }
   }
 }
 
-bool ConstantPoolCache::can_archive_resolved_method(ResolvedMethodEntry* method_entry) {
+void ConstantPoolCache::remove_resolved_indy_entries_if_non_deterministic() {
+  ConstantPool* cp = constant_pool();
+  ConstantPool* src_cp =  ArchiveBuilder::current()->get_source_addr(cp);
+  for (int i = 0; i < _resolved_indy_entries->length(); i++) {
+    ResolvedIndyEntry* rei = _resolved_indy_entries->adr_at(i);
+    int cp_index = rei->constant_pool_index();
+    bool archived = false;
+    bool resolved = rei->is_resolved();
+    if (resolved && AOTConstantPoolResolver::is_resolution_deterministic(src_cp, cp_index)) {
+      rei->mark_and_relocate();
+      archived = true;
+    } else {
+      rei->remove_unshareable_info();
+    }
+    if (resolved) {
+      LogStreamHandle(Trace, cds, resolve) log;
+      if (log.is_enabled()) {
+        ResourceMark rm;
+        int bsm = cp->bootstrap_method_ref_index_at(cp_index);
+        int bsm_ref = cp->method_handle_index_at(bsm);
+        Symbol* bsm_name = cp->uncached_name_ref_at(bsm_ref);
+        Symbol* bsm_signature = cp->uncached_signature_ref_at(bsm_ref);
+        Symbol* bsm_klass = cp->klass_name_at(cp->uncached_klass_ref_index_at(bsm_ref));
+        log.print("%s indy   CP entry [%3d]: %s (%d)",
+                  (archived ? "archived" : "reverted"),
+                  cp_index, cp->pool_holder()->name()->as_C_string(), i);
+        log.print(" %s %s.%s:%s", (archived ? "=>" : "  "), bsm_klass->as_C_string(),
+                  bsm_name->as_C_string(), bsm_signature->as_C_string());
+      }
+      ArchiveBuilder::alloc_stats()->record_indy_cp_entry(archived, resolved && !archived);
+    }
+  }
+}
+
+bool ConstantPoolCache::can_archive_invokehandle(ResolvedMethodEntry* rme) {
+  ConstantPool* cp = constant_pool();
+  assert(rme->is_resolved(Bytecodes::_invokehandle), "sanity");
+
+  int cp_index = rme->constant_pool_index();
+  int klass_cp_index = cp->uncached_klass_ref_index_at(cp_index);
+  Klass* resolved_klass = cp->resolved_klass_at(klass_cp_index);
+  if (!resolved_klass->is_instance_klass()) {
+    // FIXME: can this ever happen?
+    return false;
+  }
+  // FIXME -- any class referenced by the archived CP entries should be added to ArchiveBuilder::classes, or should be
+  // filtered out.
+  return true;
+}
+
+bool ConstantPoolCache::can_archive_resolved_method(ConstantPool* src_cp, ResolvedMethodEntry* method_entry) {
   InstanceKlass* pool_holder = constant_pool()->pool_holder();
   if (!(pool_holder->is_shared_boot_class() || pool_holder->is_shared_platform_class() ||
         pool_holder->is_shared_app_class())) {
     // Archiving resolved cp entries for classes from non-builtin loaders
     // is not yet supported.
@@ -518,26 +566,31 @@
       return false; // FIXME: corresponding stub is generated on demand during method resolution (see LinkResolver::resolve_static_call).
     }
   }
 
   int cp_index = method_entry->constant_pool_index();
-  ConstantPool* src_cp = ArchiveBuilder::current()->get_source_addr(constant_pool());
   assert(src_cp->tag_at(cp_index).is_method() || src_cp->tag_at(cp_index).is_interface_method(), "sanity");
 
-  if (!ClassPrelinker::is_resolution_deterministic(src_cp, cp_index)) {
+  if (!AOTConstantPoolResolver::is_resolution_deterministic(src_cp, cp_index)) {
     return false;
   }
 
-  if (method_entry->is_resolved(Bytecodes::_invokeinterface) ||
+  if (method_entry->is_resolved(Bytecodes::_invokestatic) ||
+      method_entry->is_resolved(Bytecodes::_invokeinterface) ||
       method_entry->is_resolved(Bytecodes::_invokevirtual) ||
       method_entry->is_resolved(Bytecodes::_invokespecial)) {
     return true;
+  } else if (method_entry->is_resolved(Bytecodes::_invokehandle)) {
+    if (CDSConfig::is_dumping_invokedynamic() && can_archive_invokehandle(method_entry)) {
+      // invokehandle depends on archived MethodType and LambdaForms.
+      return true;
+    } else {
+      return false;
+    }
   } else {
-    // invokestatic and invokehandle are not supported yet.
     return false;
   }
-
 }
 #endif // INCLUDE_CDS
 
 void ConstantPoolCache::deallocate_contents(ClassLoaderData* data) {
   assert(!is_shared(), "shared caches are not deallocated");
