diff a/src/hotspot/share/cds/aotMappedHeapWriter.cpp b/src/hotspot/share/cds/aotMappedHeapWriter.cpp
--- a/src/hotspot/share/cds/aotMappedHeapWriter.cpp
+++ b/src/hotspot/share/cds/aotMappedHeapWriter.cpp
@@ -158,11 +158,13 @@
   set_requested_address_range(heap_info);
   relocate_embedded_oops(roots, heap_info);
 }
 
 bool AOTMappedHeapWriter::is_too_large_to_archive(oop o) {
-  return is_too_large_to_archive(o->size());
+  size_t size = o->size();
+  size = o->copy_size_cds(size, o->mark());
+  return is_too_large_to_archive(size);
 }
 
 bool AOTMappedHeapWriter::is_string_too_large_to_archive(oop string) {
   typeArrayOop value = java_lang_String::value_no_keepalive(string);
   return is_too_large_to_archive(value);
@@ -245,11 +247,12 @@
 }
 
 size_t AOTMappedHeapWriter::size_of_buffered_oop(address buffered_addr) {
   oop p = buffered_addr_to_source_obj(buffered_addr);
   if (p != nullptr) {
-    return p->size();
+    size_t size = p->size();
+    return p->copy_size_cds(size, p->mark());
   }
 
   size_t nbytes = get_filler_size_at(buffered_addr);
   if (nbytes > 0) {
     assert((nbytes % BytesPerWord) == 0, "should be aligned");
@@ -530,11 +533,13 @@
   *field_addr = value;
 }
 
 size_t AOTMappedHeapWriter::copy_one_source_obj_to_buffer(oop src_obj) {
   assert(!is_too_large_to_archive(src_obj), "already checked");
-  size_t byte_size = src_obj->size() * HeapWordSize;
+  size_t old_size = src_obj->size();
+  size_t new_size = src_obj->copy_size_cds(old_size, src_obj->mark());
+  size_t byte_size = new_size * HeapWordSize;
   assert(byte_size > 0, "no zero-size objects");
 
   // For region-based collectors such as G1, the archive heap may be mapped into
   // multiple regions. We need to make sure that we don't have an object that can possible
   // span across two regions.
@@ -551,11 +556,11 @@
 
   address from = cast_from_oop<address>(src_obj);
   address to = offset_to_buffered_address<address>(_buffer_used);
   assert(is_object_aligned(_buffer_used), "sanity");
   assert(is_object_aligned(byte_size), "sanity");
-  memcpy(to, from, byte_size);
+  memcpy(to, from, MIN2(new_size, old_size) * HeapWordSize);
 
   // These native pointers will be restored explicitly at run time.
   if (java_lang_Module::is_instance(src_obj)) {
     update_buffered_object_field<ModuleEntry*>(to, java_lang_Module::module_entry_offset(), nullptr);
   } else if (java_lang_ClassLoader::is_instance(src_obj)) {
@@ -727,10 +732,11 @@
   address buffered_addr = requested_addr_to_buffered_addr(cast_from_oop<address>(requested_obj));
 
   oop fake_oop = cast_to_oop(buffered_addr);
   if (UseCompactObjectHeaders) {
     fake_oop->set_mark(markWord::prototype().set_narrow_klass(nk));
+    assert(fake_oop->mark().narrow_klass() != 0, "must not be null");
   } else {
     fake_oop->set_narrow_klass(nk);
   }
 
   if (src_obj == nullptr) {
@@ -739,18 +745,25 @@
   // We need to retain the identity_hash, because it may have been used by some hashtables
   // in the shared heap.
   if (!src_obj->fast_no_hash_check()) {
     intptr_t src_hash = src_obj->identity_hash();
     if (UseCompactObjectHeaders) {
-      fake_oop->set_mark(markWord::prototype().set_narrow_klass(nk).copy_set_hash(src_hash));
+      markWord m = markWord::prototype().set_narrow_klass(nk);
+      m = m.copy_hashctrl_from(src_obj->mark());
+      fake_oop->set_mark(m);
+      if (m.is_hashed_not_expanded()) {
+        fake_oop->set_mark(fake_oop->initialize_hash_if_necessary(src_obj, src_klass, m));
+      } else if (m.is_not_hashed_expanded()) {
+        fake_oop->set_mark(m.set_not_hashed_not_expanded());
+      }
+      assert(!fake_oop->mark().is_not_hashed_expanded() && !fake_oop->mark().is_hashed_not_expanded(), "must not be not-hashed-moved and not be hashed-not-moved");
     } else {
       fake_oop->set_mark(markWord::prototype().copy_set_hash(src_hash));
+      DEBUG_ONLY(intptr_t archived_hash = fake_oop->identity_hash());
+      assert(src_hash == archived_hash, "Different hash codes: original " INTPTR_FORMAT ", archived " INTPTR_FORMAT, src_hash, archived_hash);
     }
     assert(fake_oop->mark().is_unlocked(), "sanity");
-
-    DEBUG_ONLY(intptr_t archived_hash = fake_oop->identity_hash());
-    assert(src_hash == archived_hash, "Different hash codes: original " INTPTR_FORMAT ", archived " INTPTR_FORMAT, src_hash, archived_hash);
   }
   // Strip age bits.
   fake_oop->set_mark(fake_oop->mark().set_age(0));
 }
 
