diff a/src/hotspot/share/cds/classPrelinker.hpp b/src/hotspot/share/cds/classPrelinker.hpp
--- a/src/hotspot/share/cds/classPrelinker.hpp
+++ b/src/hotspot/share/cds/classPrelinker.hpp
@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.
@@ -23,10 +23,11 @@
  */
 
 #ifndef SHARE_CDS_CLASSPRELINKER_HPP
 #define SHARE_CDS_CLASSPRELINKER_HPP
 
+#include "interpreter/bytecodes.hpp"
 #include "oops/oopsHierarchy.hpp"
 #include "memory/allStatic.hpp"
 #include "memory/allocation.hpp"
 #include "runtime/handles.hpp"
 #include "utilities/exceptions.hpp"
@@ -35,10 +36,13 @@
 
 class ConstantPool;
 class constantPoolHandle;
 class InstanceKlass;
 class Klass;
+class SerializeClosure;
+
+template <typename T> class GrowableArray;
 
 // ClassPrelinker is used to perform ahead-of-time linking of ConstantPool entries
 // for archived InstanceKlasses.
 //
 // At run time, Java classes are loaded dynamically and may be replaced with JVMTI.
@@ -47,45 +51,56 @@
 //
 // For example, a JVM_CONSTANT_Class reference to a supertype can be safely resolved
 // at dump time, because at run time we will load a class from the CDS archive only
 // if all of its supertypes are loaded from the CDS archive.
 class ClassPrelinker :  AllStatic {
+  class PreloadedKlassRecorder;
   using ClassesTable = ResourceHashtable<InstanceKlass*, bool, 15889, AnyObj::C_HEAP, mtClassShared> ;
   static ClassesTable* _processed_classes;
-  static ClassesTable* _vm_classes;
-
-  static void add_one_vm_class(InstanceKlass* ik);
 
 #ifdef ASSERT
+  template <typename T> static bool is_in_archivebuilder_buffer(T p) {
+    return is_in_archivebuilder_buffer((address)(p));
+  }
   static bool is_in_archivebuilder_buffer(address p);
 #endif
 
-  template <typename T>
-  static bool is_in_archivebuilder_buffer(T p) {
-    return is_in_archivebuilder_buffer((address)(p));
-  }
   static void resolve_string(constantPoolHandle cp, int cp_index, TRAPS) NOT_CDS_JAVA_HEAP_RETURN;
-  static Klass* maybe_resolve_class(constantPoolHandle cp, int cp_index, TRAPS);
-  static bool can_archive_resolved_klass(InstanceKlass* cp_holder, Klass* resolved_klass);
-  static Klass* find_loaded_class(JavaThread* THREAD, oop class_loader, Symbol* name);
+  static bool is_class_resolution_deterministic(InstanceKlass* cp_holder, Klass* resolved_class);
+  static bool is_indy_resolution_deterministic(ConstantPool* cp, int cp_index);
+
+  static Klass* find_loaded_class(Thread* current, oop class_loader, Symbol* name);
+  static Klass* find_loaded_class(Thread* current, ConstantPool* cp, int class_cp_index);
+
+  // fmi = FieldRef/MethodRef/InterfaceMethodRef
+  static void maybe_resolve_fmi_ref(InstanceKlass* ik, Method* m, Bytecodes::Code bc, int raw_index,
+                                    GrowableArray<bool>* resolve_fmi_list, TRAPS);
+  // helper
+  static Klass* resolve_boot_class_or_fail(const char* class_name, TRAPS);
+
+  // java/lang/reflect/Proxy caching
+  static void init_dynamic_proxy_cache(TRAPS);
 
 public:
   static void initialize();
   static void dispose();
 
-  // Is this class resolved as part of vmClasses::resolve_all()? If so, these
-  // classes are guatanteed to be loaded at runtime (and cannot be replaced by JVMTI)
-  // when CDS is enabled. Therefore, we can safely keep a direct reference to these
-  // classes.
-  static bool is_vm_class(InstanceKlass* ik);
+  static void preresolve_class_cp_entries(JavaThread* current, InstanceKlass* ik, GrowableArray<bool>* preresolve_list);
+  static void preresolve_field_and_method_cp_entries(JavaThread* current, InstanceKlass* ik, GrowableArray<bool>* preresolve_list);
+  static void preresolve_indy_cp_entries(JavaThread* current, InstanceKlass* ik, GrowableArray<bool>* preresolve_list);
+
+  // java/lang/Class$ReflectionData caching
+  static int class_reflection_data_flags(InstanceKlass* ik, TRAPS);
+  static void generate_reflection_data(JavaThread* current, InstanceKlass* ik, int rd_flags);
+
+  // java/lang/reflect/Proxy caching
+  static void trace_dynamic_proxy_class(oop loader, const char* proxy_name, objArrayOop interfaces, int access_flags);
+  static void define_dynamic_proxy_class(Handle loader, Handle proxy_name, Handle interfaces, int access_flags, TRAPS);
 
   // Resolve all constant pool entries that are safe to be stored in the
   // CDS archive.
   static void dumptime_resolve_constants(InstanceKlass* ik, TRAPS);
 
-  // Can we resolve the klass entry at cp_index in this constant pool, and store
-  // the result in the CDS archive? Returns true if cp_index is guaranteed to
-  // resolve to the same InstanceKlass* at both dump time and run time.
-  static bool can_archive_resolved_klass(ConstantPool* cp, int cp_index);
+  static bool is_resolution_deterministic(ConstantPool* cp, int cp_index);
 };
 
 #endif // SHARE_CDS_CLASSPRELINKER_HPP
