diff a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp
--- a/src/hotspot/share/classfile/classLoader.cpp
+++ b/src/hotspot/share/classfile/classLoader.cpp
@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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.
@@ -1099,10 +1099,11 @@
 
   // Lookup stream for parsing .class file
   ClassFileStream* stream = nullptr;
   s2 classpath_index = 0;
   ClassPathEntry* e = nullptr;
+  bool is_patched = false;
 
   // If search_append_only is true, boot loader visibility boundaries are
   // set to be _first_append_entry to the end. This includes:
   //   [-Xbootclasspath/a]; [jvmti appended entries]
   //
@@ -1123,16 +1124,20 @@
     // At CDS dump time, the --patch-module entries are ignored. That means a
     // class is still loaded from the runtime image even if it might
     // appear in the _patch_mod_entries. The runtime shared class visibility
     // check will determine if a shared class is visible based on the runtime
     // environment, including the runtime --patch-module setting.
-    //
-    // Dynamic dumping requires UseSharedSpaces to be enabled. Since --patch-module
-    // is not supported with UseSharedSpaces, we can never come here during dynamic dumping.
-    assert(!CDSConfig::is_dumping_dynamic_archive(), "sanity");
-    if (!CDSConfig::is_dumping_static_archive()) {
+    if (!CDSConfig::is_valhalla_preview()) {
+      // Dynamic dumping requires UseSharedSpaces to be enabled. Since --patch-module
+      // is not supported with UseSharedSpaces, we can never come here during dynamic dumping.
+      assert(!CDSConfig::is_dumping_dynamic_archive(), "sanity");
+    }
+    if (CDSConfig::is_valhalla_preview() || !CDSConfig::is_dumping_static_archive()) {
       stream = search_module_entries(THREAD, _patch_mod_entries, class_name, file_name);
+      if (stream != nullptr) {
+        is_patched = true;
+      }
     }
   }
 
   // Load Attempt #2: [jimage | exploded build]
   if (!search_append_only && (nullptr == stream)) {
@@ -1179,10 +1184,14 @@
                                                            name,
                                                            loader_data,
                                                            cl_info,
                                                            CHECK_NULL);
   result->set_classpath_index(classpath_index);
+  if (is_patched) {
+    result->set_shared_classpath_index(0);
+    result->set_shared_class_loader_type(ClassLoader::BOOT_LOADER);
+  }
   return result;
 }
 
 #if INCLUDE_CDS
 char* ClassLoader::skip_uri_protocol(char* source) {
@@ -1214,10 +1223,14 @@
   if (ik->is_hidden()) {
     // We do not archive hidden classes.
     return;
   }
 
+  if (ik->shared_classpath_index() == 0 && ik->is_shared_boot_class()) {
+    return;
+  }
+
   oop loader = ik->class_loader();
   char* src = (char*)stream->source();
   if (src == nullptr) {
     if (loader == nullptr) {
       // JFR classes
@@ -1301,11 +1314,13 @@
     }
   } else {
     // The shared path table is set up after module system initialization.
     // The path table contains no entry before that. Any classes loaded prior
     // to the setup of the shared path table must be from the modules image.
-    assert(stream->from_boot_loader_modules_image(), "stream must be loaded by boot loader from modules image");
+    if (!CDSConfig::is_valhalla_preview()) {
+      assert(stream->from_boot_loader_modules_image(), "stream must be loaded by boot loader from modules image");
+    }
     assert(FileMapInfo::get_number_of_shared_paths() == 0, "shared path table must not have been setup");
     classpath_index = 0;
   }
 
   const char* const class_name = ik->name()->as_C_string();
