8231610: Relocate the CDS archive if it cannot be mapped to the requested address
authoriklam
Wed, 13 Nov 2019 16:36:54 -0800
changeset 59070 22ee476cc664
parent 59069 e0d59f0c2b7d
child 59071 558da4a0e31b
8231610: Relocate the CDS archive if it cannot be mapped to the requested address Reviewed-by: jiangli, coleenp, ccheung
src/hotspot/share/classfile/javaClasses.cpp
src/hotspot/share/classfile/javaClasses.hpp
src/hotspot/share/classfile/systemDictionaryShared.cpp
src/hotspot/share/classfile/systemDictionaryShared.hpp
src/hotspot/share/include/cds.h
src/hotspot/share/memory/allocation.hpp
src/hotspot/share/memory/archiveUtils.cpp
src/hotspot/share/memory/archiveUtils.hpp
src/hotspot/share/memory/dynamicArchive.cpp
src/hotspot/share/memory/dynamicArchive.hpp
src/hotspot/share/memory/filemap.cpp
src/hotspot/share/memory/filemap.hpp
src/hotspot/share/memory/heapShared.cpp
src/hotspot/share/memory/metaspace.cpp
src/hotspot/share/memory/metaspace.hpp
src/hotspot/share/memory/metaspaceClosure.hpp
src/hotspot/share/memory/metaspaceShared.cpp
src/hotspot/share/memory/metaspaceShared.hpp
src/hotspot/share/memory/universe.cpp
src/hotspot/share/oops/constMethod.cpp
src/hotspot/share/oops/instanceKlass.cpp
src/hotspot/share/oops/instanceKlass.hpp
src/hotspot/share/oops/method.cpp
src/hotspot/share/oops/method.hpp
src/hotspot/share/runtime/arguments.cpp
src/hotspot/share/runtime/arguments.hpp
src/hotspot/share/runtime/globals.hpp
src/hotspot/share/runtime/vmStructs.cpp
src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java
src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c
src/jdk.hotspot.agent/solaris/native/libsaproc/saproc.cpp
test/hotspot/jtreg/TEST.groups
test/hotspot/jtreg/runtime/cds/SpaceUtilizationCheck.java
test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java
test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveRelocationTest.java
test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java
--- a/src/hotspot/share/classfile/javaClasses.cpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/classfile/javaClasses.cpp	Wed Nov 13 16:36:54 2019 -0800
@@ -1077,7 +1077,7 @@
       Klass *ak = (Klass*)(archived_m->metadata_field(_array_klass_offset));
       assert(ak != NULL || t == T_VOID, "should not be NULL");
       if (ak != NULL) {
-        Klass *reloc_ak = MetaspaceShared::get_relocated_klass(ak);
+        Klass *reloc_ak = MetaspaceShared::get_relocated_klass(ak, true);
         archived_m->metadata_field_put(_array_klass_offset, reloc_ak);
       }
 
@@ -1222,7 +1222,7 @@
   // The archived mirror's field at _klass_offset is still pointing to the original
   // klass. Updated the field in the archived mirror to point to the relocated
   // klass in the archive.
-  Klass *reloc_k = MetaspaceShared::get_relocated_klass(as_Klass(mirror));
+  Klass *reloc_k = MetaspaceShared::get_relocated_klass(as_Klass(mirror), true);
   log_debug(cds, heap, mirror)(
     "Relocate mirror metadata field at _klass_offset from " PTR_FORMAT " ==> " PTR_FORMAT,
     p2i(as_Klass(mirror)), p2i(reloc_k));
@@ -1232,7 +1232,7 @@
   // higher array klass if exists. Relocate the pointer.
   Klass *arr = array_klass_acquire(mirror);
   if (arr != NULL) {
-    Klass *reloc_arr = MetaspaceShared::get_relocated_klass(arr);
+    Klass *reloc_arr = MetaspaceShared::get_relocated_klass(arr, true);
     log_debug(cds, heap, mirror)(
       "Relocate mirror metadata field at _array_klass_offset from " PTR_FORMAT " ==> " PTR_FORMAT,
       p2i(arr), p2i(reloc_arr));
@@ -1241,6 +1241,33 @@
   return archived_mirror;
 }
 
+void java_lang_Class::update_archived_primitive_mirror_native_pointers(oop archived_mirror) {
+  if (MetaspaceShared::relocation_delta() != 0) {
+    assert(archived_mirror->metadata_field(_klass_offset) == NULL, "must be for primitive class");
+
+    Klass* ak = ((Klass*)archived_mirror->metadata_field(_array_klass_offset));
+    if (ak != NULL) {
+      archived_mirror->metadata_field_put(_array_klass_offset,
+          (Klass*)(address(ak) + MetaspaceShared::relocation_delta()));
+    }
+  }
+}
+
+void java_lang_Class::update_archived_mirror_native_pointers(oop archived_mirror) {
+  if (MetaspaceShared::relocation_delta() != 0) {
+    Klass* k = ((Klass*)archived_mirror->metadata_field(_klass_offset));
+    archived_mirror->metadata_field_put(_klass_offset,
+        (Klass*)(address(k) + MetaspaceShared::relocation_delta()));
+
+    Klass* ak = ((Klass*)archived_mirror->metadata_field(_array_klass_offset));
+    if (ak != NULL) {
+      archived_mirror->metadata_field_put(_array_klass_offset,
+          (Klass*)(address(ak) + MetaspaceShared::relocation_delta()));
+    }
+  }
+}
+
+
 // Returns true if the mirror is updated, false if no archived mirror
 // data is present. After the archived mirror object is restored, the
 // shared klass' _has_raw_archived_mirror flag is cleared.
@@ -1256,15 +1283,15 @@
   }
 
   oop m = HeapShared::materialize_archived_object(k->archived_java_mirror_raw_narrow());
-
   if (m == NULL) {
     return false;
   }
 
+  // mirror is archived, restore
   log_debug(cds, mirror)("Archived mirror is: " PTR_FORMAT, p2i(m));
-
-  // mirror is archived, restore
   assert(HeapShared::is_archived_object(m), "must be archived mirror object");
+  update_archived_mirror_native_pointers(m);
+  assert(as_Klass(m) == k, "must be");
   Handle mirror(THREAD, m);
 
   if (!k->is_array_klass()) {
@@ -4649,6 +4676,28 @@
 }
 #endif
 
+#if INCLUDE_CDS_JAVA_HEAP
+bool JavaClasses::is_supported_for_archiving(oop obj) {
+  Klass* klass = obj->klass();
+
+  if (klass == SystemDictionary::ClassLoader_klass() ||  // ClassLoader::loader_data is malloc'ed.
+      klass == SystemDictionary::Module_klass() ||       // Module::module_entry is malloc'ed
+      // The next 3 classes are used to implement java.lang.invoke, and are not used directly in
+      // regular Java code. The implementation of java.lang.invoke uses generated anonymoys classes
+      // (e.g., as referenced by ResolvedMethodName::vmholder) that are not yet supported by CDS.
+      // So for now we cannot not support these classes for archiving.
+      //
+      // These objects typically are not referenced by static fields, but rather by resolved
+      // constant pool entries, so excluding them shouldn't affect the archiving of static fields.
+      klass == SystemDictionary::ResolvedMethodName_klass() ||
+      klass == SystemDictionary::MemberName_klass() ||
+      klass == SystemDictionary::Context_klass()) {
+    return false;
+  }
+
+  return true;
+}
+#endif
 
 #ifndef PRODUCT
 
--- a/src/hotspot/share/classfile/javaClasses.hpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/classfile/javaClasses.hpp	Wed Nov 13 16:36:54 2019 -0800
@@ -281,6 +281,8 @@
                             Handle protection_domain, TRAPS);
   static void fixup_mirror(Klass* k, TRAPS);
   static oop  create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS);
+  static void update_archived_primitive_mirror_native_pointers(oop archived_mirror) NOT_CDS_JAVA_HEAP_RETURN;
+  static void update_archived_mirror_native_pointers(oop archived_mirror) NOT_CDS_JAVA_HEAP_RETURN;
 
   // Archiving
   static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
@@ -1662,6 +1664,7 @@
   static void check_offsets() PRODUCT_RETURN;
   static void serialize_offsets(SerializeClosure* soc) NOT_CDS_RETURN;
   static InjectedField* get_injected(Symbol* class_name, int* field_count);
+  static bool is_supported_for_archiving(oop obj) NOT_CDS_JAVA_HEAP_RETURN_(false);
 };
 
 #undef DECLARE_INJECTED_FIELD_ENUM
--- a/src/hotspot/share/classfile/systemDictionaryShared.cpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp	Wed Nov 13 16:36:54 2019 -0800
@@ -38,6 +38,7 @@
 #include "classfile/vmSymbols.hpp"
 #include "logging/log.hpp"
 #include "memory/allocation.hpp"
+#include "memory/archiveUtils.hpp"
 #include "memory/filemap.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/metaspaceClosure.hpp"
@@ -294,6 +295,7 @@
     if (DynamicDumpSharedSpaces) {
       _klass = DynamicArchive::original_to_target(info._klass);
     }
+    ArchivePtrMarker::mark_pointer(&_klass);
   }
 
   bool matches(int clsfile_size, int clsfile_crc32) const {
@@ -337,6 +339,8 @@
     } else {
       *info_pointer_addr(klass) = record;
     }
+
+    ArchivePtrMarker::mark_pointer(info_pointer_addr(klass));
   }
 
   // Used by RunTimeSharedDictionary to implement OffsetCompactHashtable::EQUALS
@@ -1354,7 +1358,7 @@
       if (DynamicDumpSharedSpaces) {
         name = DynamicArchive::original_to_target(name);
       }
-      hash = primitive_hash<Symbol*>(name);
+      hash = SystemDictionaryShared::hash_for_shared_dictionary(name);
       u4 delta;
       if (DynamicDumpSharedSpaces) {
         delta = MetaspaceShared::object_delta_u4(DynamicArchive::buffer_to_target(record));
@@ -1413,7 +1417,7 @@
     return NULL;
   }
 
-  unsigned int hash = primitive_hash<Symbol*>(name);
+  unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary(name);
   const RunTimeSharedClassInfo* record = NULL;
   if (!MetaspaceShared::is_shared_dynamic(name)) {
     // The names of all shared classes in the static dict must also be in the
--- a/src/hotspot/share/classfile/systemDictionaryShared.hpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp	Wed Nov 13 16:36:54 2019 -0800
@@ -323,6 +323,12 @@
   };
 #endif
 
+  template <typename T>
+  static unsigned int hash_for_shared_dictionary(T* ptr) {
+    assert(ptr > (T*)SharedBaseAddress, "must be");
+    address p = address(ptr) - SharedBaseAddress;
+    return primitive_hash<address>(p);
+  }
 };
 
 #endif // SHARE_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP
--- a/src/hotspot/share/include/cds.h	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/include/cds.h	Wed Nov 13 16:36:54 2019 -0800
@@ -33,26 +33,29 @@
 //
 // Also, this is a C header file. Do not use C++ here.
 
-#define NUM_CDS_REGIONS 8 // this must be the same as MetaspaceShared::n_regions
+#define NUM_CDS_REGIONS 9 // this must be the same as MetaspaceShared::n_regions
 #define CDS_ARCHIVE_MAGIC 0xf00baba2
 #define CDS_DYNAMIC_ARCHIVE_MAGIC 0xf00baba8
-#define CURRENT_CDS_ARCHIVE_VERSION 8
+#define CURRENT_CDS_ARCHIVE_VERSION 9
 #define INVALID_CDS_ARCHIVE_VERSION -1
 
 struct CDSFileMapRegion {
-  int        _crc;            // crc checksum of the current space
-  size_t     _file_offset;    // sizeof(this) rounded to vm page size
-  union {
-    char*    _base;           // copy-on-write base address
-    size_t   _offset;         // offset from the compressed oop encoding base, only used
-                              // by archive heap space
-  } _addr;
-  size_t     _used;           // for setting space top on read
-  int        _read_only;      // read only space?
-  int        _allow_exec;     // executable code in space?
-  void*      _oopmap;         // bitmap for relocating embedded oops
-  size_t     _oopmap_size_in_bits;
-  int        _is_heap_region; // used in debug build only.
+  int     _crc;               // CRC checksum of this region.
+  int     _read_only;         // read only region?
+  int     _allow_exec;        // executable code in this region?
+  int     _is_heap_region;    // Used by SA and debug build.
+  int     _is_bitmap_region;  // Relocation bitmap for RO/RW/MC/MD regions (used by SA and debug build).
+  int     _mapped_from_file;  // Is this region mapped from a file?
+                              // If false, this region was initialized using os::read().
+  size_t  _file_offset;       // Data for this region starts at this offset in the archive file.
+  size_t  _mapping_offset;    // This region should be mapped at this offset from the base address
+                              // - for non-heap regions, the base address is SharedBaseAddress
+                              // - for heap regions, the base address is the compressed oop encoding base
+  size_t  _used;              // Number of bytes actually used by this region (excluding padding bytes added
+                              // for alignment purposed.
+  size_t  _oopmap_offset;     // Bitmap for relocating embedded oops (offset from SharedBaseAddress).
+  size_t  _oopmap_size_in_bits;
+  char*   _mapped_base;       // Actually mapped address (NULL if this region is not mapped).
 };
 
 struct CDSFileMapHeaderBase {
--- a/src/hotspot/share/memory/allocation.hpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/memory/allocation.hpp	Wed Nov 13 16:36:54 2019 -0800
@@ -283,11 +283,6 @@
     _shared_metaspace_top = top;
   }
 
-  static void expand_shared_metaspace_range(void* top) {
-    assert(top >= _shared_metaspace_top, "must be");
-    _shared_metaspace_top = top;
-  }
-
   static void* shared_metaspace_base() { return _shared_metaspace_base; }
   static void* shared_metaspace_top()  { return _shared_metaspace_top;  }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/memory/archiveUtils.cpp	Wed Nov 13 16:36:54 2019 -0800
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2019, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "memory/archiveUtils.hpp"
+#include "memory/metaspace.hpp"
+#include "utilities/bitMap.inline.hpp"
+
+#if INCLUDE_CDS
+
+CHeapBitMap* ArchivePtrMarker::_ptrmap = NULL;
+address* ArchivePtrMarker::_ptr_base;
+address* ArchivePtrMarker::_ptr_end;
+bool ArchivePtrMarker::_compacted;
+
+void ArchivePtrMarker::initialize(CHeapBitMap* ptrmap, address* ptr_base, address* ptr_end) {
+  assert(_ptrmap == NULL, "initialize only once");
+  _ptr_base = ptr_base;
+  _ptr_end = ptr_end;
+  _compacted = false;
+  _ptrmap = ptrmap;
+
+  // Use this as initial guesstimate. We should need less space in the
+  // archive, but if we're wrong the bitmap will be expanded automatically.
+  size_t estimated_archive_size = MetaspaceGC::capacity_until_GC();
+  // But set it smaller in debug builds so we always test the expansion code.
+  // (Default archive is about 12MB).
+  DEBUG_ONLY(estimated_archive_size = 6 * M);
+
+  // We need one bit per pointer in the archive.
+  _ptrmap->initialize(estimated_archive_size / sizeof(intptr_t));
+}
+
+void ArchivePtrMarker::mark_pointer(address* ptr_loc) {
+  assert(_ptrmap != NULL, "not initialized");
+  assert(!_compacted, "cannot mark anymore");
+
+  if (_ptr_base <= ptr_loc && ptr_loc < _ptr_end) {
+    address value = *ptr_loc;
+    if (value != NULL) {
+      assert(uintx(ptr_loc) % sizeof(intptr_t) == 0, "pointers must be stored in aligned addresses");
+      size_t idx = ptr_loc - _ptr_base;
+      if (_ptrmap->size() <= idx) {
+        _ptrmap->resize((idx + 1) * 2);
+      }
+      assert(idx < _ptrmap->size(), "must be");
+      _ptrmap->set_bit(idx);
+      //tty->print_cr("Marking pointer [%p] -> %p @ " SIZE_FORMAT_W(9), ptr_loc, *ptr_loc, idx);
+    }
+  }
+}
+
+class ArchivePtrBitmapCleaner: public BitMapClosure {
+  CHeapBitMap* _ptrmap;
+  address* _ptr_base;
+  address  _relocatable_base;
+  address  _relocatable_end;
+  size_t   _max_non_null_offset;
+
+public:
+  ArchivePtrBitmapCleaner(CHeapBitMap* ptrmap, address* ptr_base, address relocatable_base, address relocatable_end) :
+    _ptrmap(ptrmap), _ptr_base(ptr_base),
+    _relocatable_base(relocatable_base), _relocatable_end(relocatable_end), _max_non_null_offset(0) {}
+
+  bool do_bit(size_t offset) {
+    address* ptr_loc = _ptr_base + offset;
+    address  ptr_value = *ptr_loc;
+    if (ptr_value != NULL) {
+      assert(_relocatable_base <= ptr_value && ptr_value < _relocatable_end, "do not point to arbitrary locations!");
+      if (_max_non_null_offset < offset) {
+        _max_non_null_offset = offset;
+      }
+    } else {
+      _ptrmap->clear_bit(offset);
+      DEBUG_ONLY(log_trace(cds, reloc)("Clearing pointer [" PTR_FORMAT  "] -> NULL @ " SIZE_FORMAT_W(9), p2i(ptr_loc), offset));
+    }
+
+    return true;
+  }
+
+  size_t max_non_null_offset() const { return _max_non_null_offset; }
+};
+
+void ArchivePtrMarker::compact(address relocatable_base, address relocatable_end) {
+  assert(!_compacted, "cannot compact again");
+  ArchivePtrBitmapCleaner cleaner(_ptrmap, _ptr_base, relocatable_base, relocatable_end);
+  _ptrmap->iterate(&cleaner);
+  compact(cleaner.max_non_null_offset());
+}
+
+void ArchivePtrMarker::compact(size_t max_non_null_offset) {
+  assert(!_compacted, "cannot compact again");
+  _ptrmap->resize(max_non_null_offset + 1);
+  _compacted = true;
+}
+
+#endif // INCLUDE_CDS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/memory/archiveUtils.hpp	Wed Nov 13 16:36:54 2019 -0800
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2019, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_MEMORY_ARCHIVEUTILS_HPP
+#define SHARE_MEMORY_ARCHIVEUTILS_HPP
+
+#include "logging/log.hpp"
+#include "runtime/arguments.hpp"
+#include "utilities/bitMap.hpp"
+
+// ArchivePtrMarker is used to mark the location of pointers embedded in a CDS archive. E.g., when an
+// InstanceKlass k is dumped, we mark the location of the k->_name pointer by effectively calling
+// mark_pointer(/*ptr_loc=*/&k->_name). It's required that (_prt_base <= ptr_loc < _ptr_end). _ptr_base is
+// fixed, but _ptr_end can be expanded as more objects are dumped.
+class ArchivePtrMarker : AllStatic {
+  static CHeapBitMap* _ptrmap;
+  static address*     _ptr_base;
+  static address*     _ptr_end;
+
+  // Once _ptrmap is compacted, we don't allow bit marking anymore. This is to
+  // avoid unintentional copy operations after the bitmap has been finalized and written.
+  static bool         _compacted;
+public:
+  static void initialize(CHeapBitMap* ptrmap, address* ptr_base, address* ptr_end);
+  static void mark_pointer(address* ptr_loc);
+  static void compact(address relocatable_base, address relocatable_end);
+  static void compact(size_t max_non_null_offset);
+
+  template <typename T>
+  static void mark_pointer(T* ptr_loc) {
+    mark_pointer((address*)ptr_loc);
+  }
+
+  static void expand_ptr_end(address *new_ptr_end) {
+    assert(_ptr_end <= new_ptr_end, "must be");
+    _ptr_end = new_ptr_end;
+  }
+
+  static CHeapBitMap* ptrmap() {
+    return _ptrmap;
+  }
+};
+
+// SharedDataRelocator is used to shift pointers in the CDS archive.
+//
+// The CDS archive is basically a contiguous block of memory (divided into several regions)
+// that contains multiple objects. The objects may contain direct pointers that point to other objects
+// within the archive (e.g., InstanceKlass::_name points to a Symbol in the archive). During dumping, we
+// built a bitmap that marks the locations of all these pointers (using ArchivePtrMarker, see comments above).
+//
+// The contents of the archive assumes that it’s mapped at the default SharedBaseAddress (e.g. 0x800000000).
+// If the archive ends up being mapped at a different address (e.g. 0x810000000), SharedDataRelocator
+// is used to shift each marked pointer by a delta (0x10000000 in this example), so that it points to
+// the actually mapped location of the target object.
+template <bool COMPACTING>
+class SharedDataRelocator: public BitMapClosure {
+  // for all (address** p), where (is_marked(p) && _patch_base <= p && p < _patch_end) { *p += delta; }
+
+  // Patch all pointers within this region that are marked.
+  address* _patch_base;
+  address* _patch_end;
+
+  // Before patching, all pointers must point to this region.
+  address _valid_old_base;
+  address _valid_old_end;
+
+  // After patching, all pointers must point to this region.
+  address _valid_new_base;
+  address _valid_new_end;
+
+  // How much to relocate for each pointer.
+  intx _delta;
+
+  // The following fields are used only when COMPACTING == true;
+  // The highest offset (inclusive) in the bitmap that contains a non-null pointer.
+  // This is used at dump time to reduce the size of the bitmap (which may have been over-allocated).
+  size_t _max_non_null_offset;
+  CHeapBitMap* _ptrmap;
+
+ public:
+  SharedDataRelocator(address* patch_base, address* patch_end,
+                      address valid_old_base, address valid_old_end,
+                      address valid_new_base, address valid_new_end, intx delta,
+                      CHeapBitMap* ptrmap = NULL) :
+    _patch_base(patch_base), _patch_end(patch_end),
+    _valid_old_base(valid_old_base), _valid_old_end(valid_old_end),
+    _valid_new_base(valid_new_base), _valid_new_end(valid_new_end),
+    _delta(delta) {
+    log_debug(cds, reloc)("SharedDataRelocator::_patch_base     = " PTR_FORMAT, p2i(_patch_base));
+    log_debug(cds, reloc)("SharedDataRelocator::_patch_end      = " PTR_FORMAT, p2i(_patch_end));
+    log_debug(cds, reloc)("SharedDataRelocator::_valid_old_base = " PTR_FORMAT, p2i(_valid_old_base));
+    log_debug(cds, reloc)("SharedDataRelocator::_valid_old_end  = " PTR_FORMAT, p2i(_valid_old_end));
+    log_debug(cds, reloc)("SharedDataRelocator::_valid_new_base = " PTR_FORMAT, p2i(_valid_new_base));
+    log_debug(cds, reloc)("SharedDataRelocator::_valid_new_end  = " PTR_FORMAT, p2i(_valid_new_end));
+    if (COMPACTING) {
+      assert(ptrmap != NULL, "must be");
+      _max_non_null_offset = 0;
+      _ptrmap = ptrmap;
+    } else {
+      // Don't touch the _max_non_null_offset and _ptrmap fields. Hopefully a good C++ compiler can
+      // elide them.
+      assert(ptrmap == NULL, "must be");
+    }
+  }
+
+  size_t max_non_null_offset() {
+    assert(COMPACTING, "must be");
+    return _max_non_null_offset;
+  }
+
+  inline bool do_bit(size_t offset);
+};
+
+
+#endif // SHARE_MEMORY_ARCHIVEUTILS_HPP
--- a/src/hotspot/share/memory/dynamicArchive.cpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/memory/dynamicArchive.cpp	Wed Nov 13 16:36:54 2019 -0800
@@ -29,12 +29,13 @@
 #include "classfile/systemDictionary.hpp"
 #include "classfile/systemDictionaryShared.hpp"
 #include "logging/log.hpp"
+#include "memory/archiveUtils.inline.hpp"
+#include "memory/dynamicArchive.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/metaspace.hpp"
 #include "memory/metaspaceClosure.hpp"
 #include "memory/metaspaceShared.hpp"
 #include "memory/resourceArea.hpp"
-#include "memory/dynamicArchive.hpp"
 #include "oops/compressedOops.hpp"
 #include "oops/objArrayKlass.hpp"
 #include "prims/jvmtiRedefineClasses.hpp"
@@ -50,7 +51,6 @@
 #endif
 
 class DynamicArchiveBuilder : ResourceObj {
-  CHeapBitMap _ptrmap;
   static unsigned my_hash(const address& a) {
     return primitive_hash<address>(a);
   }
@@ -64,7 +64,7 @@
       16384, ResourceObj::C_HEAP> RelocationTable;
   RelocationTable _new_loc_table;
 
-  intx _buffer_to_target_delta;
+  static intx _buffer_to_target_delta;
 
   DumpRegion* _current_dump_space;
 
@@ -77,10 +77,7 @@
 
 public:
   void mark_pointer(address* ptr_loc) {
-    if (is_in_buffer_space(ptr_loc)) {
-      size_t idx = pointer_delta(ptr_loc, _alloc_bottom, sizeof(address));
-      _ptrmap.set_bit(idx);
-    }
+    ArchivePtrMarker::mark_pointer(ptr_loc);
   }
 
   DumpRegion* current_dump_space() const {
@@ -128,6 +125,28 @@
     return pp != NULL;
   }
 
+  static int dynamic_dump_method_comparator(Method* a, Method* b) {
+    Symbol* a_name = a->name();
+    Symbol* b_name = b->name();
+
+    if (a_name == b_name) {
+      return 0;
+    }
+
+    if (!MetaspaceShared::is_in_shared_metaspace(a_name)) {
+      // a_name points to a Symbol in the top archive.
+      // When this method is called, a_name is still pointing to the output space.
+      // Translate it to point to the output space, so that it can be compared with
+      // Symbols in the base archive.
+      a_name = (Symbol*)(address(a_name) + _buffer_to_target_delta);
+    }
+    if (!MetaspaceShared::is_in_shared_metaspace(b_name)) {
+      b_name = (Symbol*)(address(b_name) + _buffer_to_target_delta);
+    }
+
+    return a_name->fast_compare(b_name);
+  }
+
 protected:
   enum FollowMode {
     make_a_copy, point_to_it, set_to_null
@@ -240,6 +259,16 @@
 
       return true; // keep recursing until every object is visited exactly once.
     }
+
+    virtual void push_special(SpecialRef type, Ref* ref, intptr_t* p) {
+      assert(type == _method_entry_ref, "only special type allowed for now");
+      address obj = ref->obj();
+      address new_obj = _builder->get_new_loc(ref);
+      size_t offset = pointer_delta(p, obj,  sizeof(u1));
+      intptr_t* new_p = (intptr_t*)(new_obj + offset);
+      assert(*p == *new_p, "must be a copy");
+      ArchivePtrMarker::mark_pointer((address*)new_p);
+    }
   };
 
   class EmbeddedRefUpdater: public MetaspaceClosure {
@@ -331,7 +360,7 @@
   public:
     EmbeddedRefMarker(DynamicArchiveBuilder* shuffler) : _builder(shuffler) {}
     virtual bool do_ref(Ref* ref, bool read_only) {
-      if (ref->not_null() && _builder->is_in_buffer_space(ref->obj())) {
+      if (ref->not_null()) {
         _builder->mark_pointer(ref->addr());
       }
       return false; // Do not recurse.
@@ -441,10 +470,10 @@
                             p2i(obj), p2i(p), bytes,
                             MetaspaceObj::type_name(ref->msotype()));
     memcpy(p, obj, bytes);
-
     intptr_t* cloned_vtable = MetaspaceShared::fix_cpp_vtable_for_dynamic_archive(ref->msotype(), p);
     if (cloned_vtable != NULL) {
       update_pointer((address*)p, (address)cloned_vtable, "vtb", 0, /*is_mso_pointer*/false);
+      mark_pointer((address*)p);
     }
 
     return (address)p;
@@ -551,6 +580,9 @@
     address reserved_bottom = reserve_space_and_init_buffer_to_target_delta();
     init_header(reserved_bottom);
 
+    CHeapBitMap ptrmap;
+    ArchivePtrMarker::initialize(&ptrmap, (address*)reserved_bottom, (address*)current_dump_space()->top());
+
     verify_estimate_size(sizeof(DynamicArchiveHeader), "header");
 
     log_info(cds, dynamic)("Copying %d klasses and %d symbols",
@@ -576,10 +608,6 @@
       iterate_roots(&ro_copier);
     }
 
-    size_t bitmap_size = pointer_delta(current_dump_space()->top(),
-                                       _alloc_bottom, sizeof(address));
-    _ptrmap.initialize(bitmap_size);
-
     {
       log_info(cds)("Relocating embedded pointers ... ");
       ResourceMark rm;
@@ -653,7 +681,7 @@
       it->push(&_symbols->at(i));
     }
 
-    _header->shared_path_table_metaspace_pointers_do(it);
+    FileMapInfo::metaspace_pointers_do(it);
 
     // Do not call these again, as we have already collected all the classes and symbols
     // that we want to archive. Also, these calls would corrupt the tables when
@@ -666,6 +694,9 @@
   }
 };
 
+intx DynamicArchiveBuilder::_buffer_to_target_delta;
+
+
 size_t DynamicArchiveBuilder::estimate_archive_size() {
   // size of the symbol table and two dictionaries, plus the RunTimeSharedClassInfo's
   _estimated_hashtable_bytes = 0;
@@ -688,26 +719,16 @@
 
 address DynamicArchiveBuilder::reserve_space_and_init_buffer_to_target_delta() {
   size_t total = estimate_archive_size();
-  bool large_pages = false; // No large pages when dumping the CDS archive.
-  size_t increment = align_up(1*G, reserve_alignment());
-  char* addr = (char*)align_up(CompressedKlassPointers::base() + MetaspaceSize + increment,
-                               reserve_alignment());
-
-  ReservedSpace* rs = MetaspaceShared::reserve_shared_rs(
-                          total, reserve_alignment(), large_pages, addr);
-  while (!rs->is_reserved() && (addr + increment > addr)) {
-    addr += increment;
-    rs = MetaspaceShared::reserve_shared_rs(
-           total, reserve_alignment(), large_pages, addr);
-  }
-  if (!rs->is_reserved()) {
+  ReservedSpace rs = MetaspaceShared::reserve_shared_space(total);
+  if (!rs.is_reserved()) {
     log_error(cds, dynamic)("Failed to reserve %d bytes of output buffer.", (int)total);
     vm_direct_exit(0);
   }
 
-  address buffer_base = (address)rs->base();
+  address buffer_base = (address)rs.base();
   log_info(cds, dynamic)("Reserved output buffer space at    : " PTR_FORMAT " [%d bytes]",
                          p2i(buffer_base), (int)total);
+  MetaspaceShared::set_shared_rs(rs);
 
   // At run time, we will mmap the dynamic archive at target_space_bottom.
   // However, at dump time, we may not be able to write into the target_space,
@@ -788,6 +809,7 @@
 void DynamicArchiveBuilder::make_klasses_shareable() {
   int i, count = _klasses->length();
 
+  InstanceKlass::disable_method_binary_search();
   for (i = 0; i < count; i++) {
     InstanceKlass* ik = _klasses->at(i);
     sort_methods(ik);
@@ -847,18 +869,24 @@
   }
 
 #ifdef ASSERT
-  {
+  if (ik->methods() != NULL) {
     for (int m = 0; m < ik->methods()->length(); m++) {
       Symbol* name = ik->methods()->at(m)->name();
       assert(MetaspaceShared::is_in_shared_metaspace(name) || is_in_buffer_space(name), "must be");
     }
   }
+  if (ik->default_methods() != NULL) {
+    for (int m = 0; m < ik->default_methods()->length(); m++) {
+      Symbol* name = ik->default_methods()->at(m)->name();
+      assert(MetaspaceShared::is_in_shared_metaspace(name) || is_in_buffer_space(name), "must be");
+    }
+  }
 #endif
 
   Thread* THREAD = Thread::current();
-  Method::sort_methods(ik->methods());
+  Method::sort_methods(ik->methods(), /*set_idnums=*/true, dynamic_dump_method_comparator);
   if (ik->default_methods() != NULL) {
-    Method::sort_methods(ik->default_methods(), /*set_idnums=*/false);
+    Method::sort_methods(ik->default_methods(), /*set_idnums=*/false, dynamic_dump_method_comparator);
   }
   ik->vtable().initialize_vtable(true, THREAD); assert(!HAS_PENDING_EXCEPTION, "cannot fail");
   ik->itable().initialize_itable(true, THREAD); assert(!HAS_PENDING_EXCEPTION, "cannot fail");
@@ -902,14 +930,60 @@
   }
 };
 
-
 void DynamicArchiveBuilder::relocate_buffer_to_target() {
   RelocateBufferToTarget patcher(this, (address*)_alloc_bottom, _buffer_to_target_delta);
-  _ptrmap.iterate(&patcher);
+  ArchivePtrMarker::ptrmap()->iterate(&patcher);
+
+  Array<u8>* table = FileMapInfo::shared_path_table().table();
+  SharedPathTable runtime_table(to_target(table), FileMapInfo::shared_path_table().size());
+  _header->set_shared_path_table(runtime_table);
+
+  address relocatable_base = (address)SharedBaseAddress;
+  address relocatable_end = (address)(current_dump_space()->top()) + _buffer_to_target_delta;
+
+  intx addr_delta = MetaspaceShared::final_delta();
+  if (addr_delta == 0) {
+    ArchivePtrMarker::compact(relocatable_base, relocatable_end);
+  } else {
+    // The base archive is NOT mapped at Arguments::default_SharedBaseAddress() (due to ASLR).
+    // This means that the current content of the dynamic archive is based on a random
+    // address. Let's relocate all the pointers, so that it can be mapped to
+    // Arguments::default_SharedBaseAddress() without runtime relocation.
+    //
+    // Note: both the base and dynamic archive are written with
+    // FileMapHeader::_shared_base_address == Arguments::default_SharedBaseAddress()
+
+    // Patch all pointers that are marked by ptrmap within this region,
+    // where we have just dumped all the metaspace data.
+    address patch_base = (address)_alloc_bottom;
+    address patch_end  = (address)current_dump_space()->top();
 
-  Array<u8>* table = _header->shared_path_table().table();
-  table = to_target(table);
- _header->relocate_shared_path_table(table);
+    // the current value of the pointers to be patched must be within this
+    // range (i.e., must point to either the top archive (as currently mapped), or to the
+    // (targeted address of) the top archive)
+    address valid_old_base = relocatable_base;
+    address valid_old_end  = relocatable_end;
+    size_t base_plus_top_size = valid_old_end - valid_old_base;
+    size_t top_size = patch_end - patch_base;
+    size_t base_size = base_plus_top_size - top_size;
+    assert(base_plus_top_size > base_size, "no overflow");
+    assert(base_plus_top_size > top_size, "no overflow");
+
+    // after patching, the pointers must point inside this range
+    // (the requested location of the archive, as mapped at runtime).
+    address valid_new_base = (address)Arguments::default_SharedBaseAddress();
+    address valid_new_end  = valid_new_base + base_plus_top_size;
+
+    log_debug(cds)("Relocating archive from [" INTPTR_FORMAT " - " INTPTR_FORMAT "] to "
+                   "[" INTPTR_FORMAT " - " INTPTR_FORMAT "], delta = " INTX_FORMAT " bytes",
+                   p2i(patch_base + base_size), p2i(patch_end),
+                   p2i(valid_new_base + base_size), p2i(valid_new_end), addr_delta);
+
+    SharedDataRelocator<true> patcher((address*)patch_base, (address*)patch_end, valid_old_base, valid_old_end,
+                                      valid_new_base, valid_new_end, addr_delta, ArchivePtrMarker::ptrmap());
+    ArchivePtrMarker::ptrmap()->iterate(&patcher);
+    ArchivePtrMarker::compact(patcher.max_non_null_offset());
+  }
 }
 
 void DynamicArchiveBuilder::write_regions(FileMapInfo* dynamic_info) {
@@ -925,6 +999,7 @@
                              MetaspaceShared::misc_code_dump_space()->base(),
                              MetaspaceShared::misc_code_dump_space()->used(),
                              /*read_only=*/false,/*allow_exec=*/true);
+  dynamic_info->write_bitmap_region(ArchivePtrMarker::ptrmap());
 }
 
 void DynamicArchiveBuilder::write_archive(char* serialized_data_start) {
@@ -940,6 +1015,7 @@
   const char* archive_name = Arguments::GetSharedDynamicArchivePath();
   dynamic_info->open_for_write(archive_name);
   write_regions(dynamic_info);
+  dynamic_info->set_final_requested_base((char*)Arguments::default_SharedBaseAddress());
   dynamic_info->set_header_crc(dynamic_info->compute_header_crc());
   dynamic_info->write_header();
   dynamic_info->close();
@@ -948,6 +1024,8 @@
   address top  = address(current_dump_space()->top()) + _buffer_to_target_delta;
   size_t file_size = pointer_delta(top, base, sizeof(char));
 
+  base += MetaspaceShared::final_delta();
+  top += MetaspaceShared::final_delta();
   log_info(cds, dynamic)("Written dynamic archive " PTR_FORMAT " - " PTR_FORMAT
                          " [" SIZE_FORMAT " bytes header, " SIZE_FORMAT " bytes total]",
                          p2i(base), p2i(top), _header->header_size(), file_size);
@@ -1036,79 +1114,8 @@
 }
 
 
-static DynamicArchiveHeader *_dynamic_header = NULL;
 DynamicArchiveBuilder* DynamicArchive::_builder = NULL;
 
-void DynamicArchive::map_failed(FileMapInfo* mapinfo) {
-  if (mapinfo->dynamic_header() != NULL) {
-    os::free((void*)mapinfo->dynamic_header());
-  }
-  delete mapinfo;
-}
-
-// Returns the top of the mapped address space
-address DynamicArchive::map() {
-  assert(UseSharedSpaces, "Sanity");
-
-  // Create the dynamic archive map info
-  FileMapInfo* mapinfo;
-  const char* filename = Arguments::GetSharedDynamicArchivePath();
-  struct stat st;
-  address result;
-  if ((filename != NULL) && (os::stat(filename, &st) == 0)) {
-    mapinfo = new FileMapInfo(false);
-    if (!mapinfo->open_for_read(filename)) {
-      result = NULL;
-    }
-    result = map_impl(mapinfo);
-    if (result == NULL) {
-      map_failed(mapinfo);
-      mapinfo->restore_shared_path_table();
-    }
-  } else {
-    if (filename != NULL) {
-      log_warning(cds, dynamic)("specified dynamic archive doesn't exist: %s", filename);
-    }
-    result = NULL;
-  }
-  return result;
-}
-
-address DynamicArchive::map_impl(FileMapInfo* mapinfo) {
-  // Read header
-  if (!mapinfo->initialize(false)) {
-    return NULL;
-  }
-
-  _dynamic_header = mapinfo->dynamic_header();
-  int regions[] = {MetaspaceShared::rw,
-                   MetaspaceShared::ro,
-                   MetaspaceShared::mc};
-
-  size_t len = sizeof(regions)/sizeof(int);
-  char* saved_base[] = {NULL, NULL, NULL};
-  char* top = mapinfo->map_regions(regions, saved_base, len);
-  if (top == NULL) {
-    mapinfo->unmap_regions(regions, saved_base, len);
-    FileMapInfo::fail_continue("Unable to use dynamic archive. Failed map_region for using -Xshare:on.");
-    return NULL;
-  }
-
-  if (!validate(mapinfo)) {
-    return NULL;
-  }
-
-  if (_dynamic_header == NULL) {
-    return NULL;
-  }
-
-  intptr_t* buffer = (intptr_t*)_dynamic_header->serialized_data_start();
-  ReadClosure rc(&buffer);
-  SymbolTable::serialize_shared_table_header(&rc, false);
-  SystemDictionaryShared::serialize_dictionary_headers(&rc, false);
-
-  return (address)top;
-}
 
 bool DynamicArchive::validate(FileMapInfo* dynamic_info) {
   // Check if the recorded base archive matches with the current one
@@ -1136,11 +1143,3 @@
   }
   return true;
 }
-
-bool DynamicArchive::is_mapped() {
-  return (_dynamic_header != NULL);
-}
-
-void DynamicArchive::disable() {
-  _dynamic_header = NULL;
-}
--- a/src/hotspot/share/memory/dynamicArchive.hpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/memory/dynamicArchive.hpp	Wed Nov 13 16:36:54 2019 -0800
@@ -99,13 +99,8 @@
   // archive?
   static bool is_in_target_space(void *obj);
 
-  static address map();
-  static bool is_mapped();
+  static bool is_mapped() { return FileMapInfo::dynamic_info() != NULL; }
   static bool validate(FileMapInfo* dynamic_info);
-  static void disable();
-private:
-  static address map_impl(FileMapInfo* mapinfo);
-  static void map_failed(FileMapInfo* mapinfo);
 };
 #endif // INCLUDE_CDS
 #endif // SHARE_VM_MEMORY_DYNAMICARCHIVE_HPP
--- a/src/hotspot/share/memory/filemap.cpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/memory/filemap.cpp	Wed Nov 13 16:36:54 2019 -0800
@@ -34,6 +34,7 @@
 #include "logging/log.hpp"
 #include "logging/logStream.hpp"
 #include "logging/logMessage.hpp"
+#include "memory/archiveUtils.inline.hpp"
 #include "memory/dynamicArchive.hpp"
 #include "memory/filemap.hpp"
 #include "memory/heapShared.inline.hpp"
@@ -55,6 +56,7 @@
 #include "runtime/vm_version.hpp"
 #include "services/memTracker.hpp"
 #include "utilities/align.hpp"
+#include "utilities/bitMap.inline.hpp"
 #include "utilities/classpathStream.hpp"
 #include "utilities/defaultStream.hpp"
 #if INCLUDE_G1GC
@@ -69,9 +71,6 @@
 #define O_BINARY 0     // otherwise do nothing.
 #endif
 
-extern address JVM_FunctionAtStart();
-extern address JVM_FunctionAtEnd();
-
 // Complain and stop. All error conditions occurring during the writing of
 // an archive file should stop the process.  Unrecoverable errors during
 // the reading of the archive file should stop the process.
@@ -104,12 +103,6 @@
 void FileMapInfo::fail_continue(const char *msg, ...) {
   va_list ap;
   va_start(ap, msg);
-  if (_dynamic_archive_info == NULL) {
-    MetaspaceShared::set_archive_loading_failed();
-  } else {
-    // _dynamic_archive_info has been setup after mapping the base archive
-    DynamicArchive::disable();
-  }
   if (PrintSharedArchiveAndExit && _validating_shared_path_table) {
     // If we are doing PrintSharedArchiveAndExit and some of the classpath entries
     // do not validate, we can still continue "limping" to validate the remaining
@@ -128,15 +121,6 @@
         ls.vprint_cr(msg, ap);
       }
     }
-    if (_dynamic_archive_info == NULL) {
-      UseSharedSpaces = false;
-      assert(current_info() != NULL, "singleton must be registered");
-      current_info()->close();
-    } else {
-      // We are failing when loading the top archive, but the base archive should
-      // continue to work.
-      log_warning(cds, dynamic)("Unable to use shared archive. The top archive failed to load: %s", _dynamic_archive_info->_full_path);
-    }
   }
   va_end(ap);
 }
@@ -227,9 +211,7 @@
   _narrow_oop_base = CompressedOops::base();
   _narrow_oop_shift = CompressedOops::shift();
   _max_heap_size = MaxHeapSize;
-  _narrow_klass_base = CompressedKlassPointers::base();
   _narrow_klass_shift = CompressedKlassPointers::shift();
-  _shared_path_table = mapinfo->_shared_path_table;
   if (HeapShared::is_heap_object_archiving_allowed()) {
     _heap_end = CompressedOops::end();
   }
@@ -249,11 +231,16 @@
   _verify_local = BytecodeVerificationLocal;
   _verify_remote = BytecodeVerificationRemote;
   _has_platform_or_app_classes = ClassLoaderExt::has_platform_or_app_classes();
-  _shared_base_address = SharedBaseAddress;
+  _requested_base_address = (char*)SharedBaseAddress;
+  _mapped_base_address = (char*)SharedBaseAddress;
   _allow_archiving_with_java_agent = AllowArchivingWithJavaAgent;
   // the following 2 fields will be set in write_header for dynamic archive header
   _base_archive_name_size = 0;
   _base_archive_is_default = false;
+
+  if (!DynamicDumpSharedSpaces) {
+    set_shared_path_table(mapinfo->_shared_path_table);
+  }
 }
 
 void SharedClassPathEntry::init_as_non_existent(const char* path, TRAPS) {
@@ -615,9 +602,11 @@
   return path_array;
 }
 
-bool FileMapInfo::fail(const char* msg, const char* name) {
+bool FileMapInfo::classpath_failure(const char* msg, const char* name) {
   ClassLoader::trace_class_path(msg, name);
-  MetaspaceShared::set_archive_loading_failed();
+  if (PrintSharedArchiveAndExit) {
+    MetaspaceShared::set_archive_loading_failed();
+  }
   return false;
 }
 
@@ -692,7 +681,7 @@
 
   if (mismatch) {
     // The paths are different
-    return fail("[BOOT classpath mismatch, actual =", runtime_boot_path);
+    return classpath_failure("[BOOT classpath mismatch, actual =", runtime_boot_path);
   }
   return true;
 }
@@ -703,7 +692,7 @@
   int rp_len = num_paths(appcp);
   bool mismatch = false;
   if (rp_len < shared_app_paths_len) {
-    return fail("Run time APP classpath is shorter than the one at dump time: ", appcp);
+    return classpath_failure("Run time APP classpath is shorter than the one at dump time: ", appcp);
   }
   if (shared_app_paths_len != 0 && rp_len != 0) {
     // Prefix is OK: E.g., dump with -cp foo.jar, but run with -cp foo.jar:bar.jar.
@@ -711,7 +700,7 @@
     GrowableArray<const char*>* rp_array = create_path_array(appcp);
     if (rp_array->length() == 0) {
       // None of the jar file specified in the runtime -cp exists.
-      return fail("None of the jar file specified in the runtime -cp exists: -Djava.class.path=", appcp);
+      return classpath_failure("None of the jar file specified in the runtime -cp exists: -Djava.class.path=", appcp);
     }
 
     // Handling of non-existent entries in the classpath: we eliminate all the non-existent
@@ -726,7 +715,7 @@
     int j = header()->app_class_paths_start_index();
     mismatch = check_paths(j, shared_app_paths_len, rp_array);
     if (mismatch) {
-      return fail("[APP classpath mismatch, actual: -Djava.class.path=", appcp);
+      return classpath_failure("[APP classpath mismatch, actual: -Djava.class.path=", appcp);
     }
   }
   return true;
@@ -952,8 +941,8 @@
 
 // Read the FileMapInfo information from the file.
 
-bool FileMapInfo::init_from_file(int fd, bool is_static) {
-  size_t sz = is_static ? sizeof(FileMapHeader) : sizeof(DynamicArchiveHeader);
+bool FileMapInfo::init_from_file(int fd) {
+  size_t sz = is_static() ? sizeof(FileMapHeader) : sizeof(DynamicArchiveHeader);
   size_t n = os::read(fd, header(), (unsigned int)sz);
   if (n != sz) {
     fail_continue("Unable to read the file header.");
@@ -965,7 +954,7 @@
     return false;
   }
 
-  unsigned int expected_magic = is_static ? CDS_ARCHIVE_MAGIC : CDS_DYNAMIC_ARCHIVE_MAGIC;
+  unsigned int expected_magic = is_static() ? CDS_ARCHIVE_MAGIC : CDS_DYNAMIC_ARCHIVE_MAGIC;
   if (header()->magic() != expected_magic) {
     log_info(cds)("_magic expected: 0x%08x", expected_magic);
     log_info(cds)("         actual: 0x%08x", header()->magic());
@@ -1016,7 +1005,7 @@
 
   _file_offset = n + header()->base_archive_name_size(); // accounts for the size of _base_archive_name
 
-  if (is_static) {
+  if (is_static()) {
     // just checking the last region is sufficient since the archive is written
     // in sequential order
     size_t len = lseek(fd, 0, SEEK_END);
@@ -1026,8 +1015,6 @@
       fail_continue("The shared archive file has been truncated.");
       return false;
     }
-
-    SharedBaseAddress = header()->shared_base_address();
   }
 
   return true;
@@ -1040,23 +1027,27 @@
 }
 
 // Read the FileMapInfo information from the file.
-bool FileMapInfo::open_for_read(const char* path) {
+bool FileMapInfo::open_for_read() {
   if (_file_open) {
     return true;
   }
-  if (path == NULL) {
+  if (is_static()) {
     _full_path = Arguments::GetSharedArchivePath();
   } else {
-    _full_path = path;
+    _full_path = Arguments::GetSharedDynamicArchivePath();
   }
   int fd = os::open(_full_path, O_RDONLY | O_BINARY, 0);
   if (fd < 0) {
-    if (errno == ENOENT) {
-      // Not locating the shared archive is ok.
-      fail_continue("Specified shared archive not found (%s).", _full_path);
+    if (is_static()) {
+      if (errno == ENOENT) {
+        // Not locating the shared archive is ok.
+        fail_continue("Specified shared archive not found (%s).", _full_path);
+      } else {
+        fail_continue("Failed to open shared archive file (%s).",
+                      os::strerror(errno));
+      }
     } else {
-      fail_continue("Failed to open shared archive file (%s).",
-                    os::strerror(errno));
+      log_warning(cds, dynamic)("specified dynamic archive doesn't exist: %s", _full_path);
     }
     return false;
   }
@@ -1127,25 +1118,35 @@
   }
 }
 
-void FileMapRegion::init(bool is_heap_region, char* base, size_t size, bool read_only,
+size_t FileMapRegion::used_aligned() const {
+  return align_up(used(), os::vm_allocation_granularity());
+}
+
+void FileMapRegion::init(int region_index, char* base, size_t size, bool read_only,
                          bool allow_exec, int crc) {
-  _is_heap_region = is_heap_region;
+  _is_heap_region = HeapShared::is_heap_region(region_index);
+  _is_bitmap_region = (region_index == MetaspaceShared::bm);
+  _mapping_offset = 0;
 
-  if (is_heap_region) {
+  if (_is_heap_region) {
     assert(!DynamicDumpSharedSpaces, "must be");
     assert((base - (char*)CompressedKlassPointers::base()) % HeapWordSize == 0, "Sanity");
     if (base != NULL) {
-      _addr._offset = (intx)CompressedOops::encode_not_null((oop)base);
-    } else {
-      _addr._offset = 0;
+      _mapping_offset = (size_t)CompressedOops::encode_not_null((oop)base);
+      assert(_mapping_offset >> 32 == 0, "must be 32-bit only");
     }
   } else {
-    _addr._base = base;
+    if (base != NULL) {
+      assert(base >= (char*)SharedBaseAddress, "must be");
+      _mapping_offset = base - (char*)SharedBaseAddress;
+    }
   }
   _used = size;
   _read_only = read_only;
   _allow_exec = allow_exec;
   _crc = crc;
+  _mapped_from_file = false;
+  _mapped_base = NULL;
 }
 
 void FileMapInfo::write_region(int region, char* base, size_t size,
@@ -1153,25 +1154,47 @@
   Arguments::assert_is_dumping_archive();
 
   FileMapRegion* si = space_at(region);
-  char* target_base = base;
-  if (DynamicDumpSharedSpaces) {
-    assert(!HeapShared::is_heap_region(region), "dynamic archive doesn't support heap regions");
-    target_base = DynamicArchive::buffer_to_target(base);
+  char* target_base;
+
+  if (region == MetaspaceShared::bm) {
+    target_base = NULL; // always NULL for bm region.
+  } else {
+    if (DynamicDumpSharedSpaces) {
+      assert(!HeapShared::is_heap_region(region), "dynamic archive doesn't support heap regions");
+      target_base = DynamicArchive::buffer_to_target(base);
+    } else {
+      target_base = base;
+    }
   }
 
   si->set_file_offset(_file_offset);
-  log_info(cds)("Shared file region %d: " SIZE_FORMAT_HEX_W(08)
+  char* requested_base = (target_base == NULL) ? NULL : target_base + MetaspaceShared::final_delta();
+  log_info(cds)("Shared file region  %d: " SIZE_FORMAT_HEX_W(08)
                 " bytes, addr " INTPTR_FORMAT " file offset " SIZE_FORMAT_HEX_W(08),
-                region, size, p2i(target_base), _file_offset);
+                region, size, p2i(requested_base), _file_offset);
 
   int crc = ClassLoader::crc32(0, base, (jint)size);
-  si->init(HeapShared::is_heap_region(region), target_base, size, read_only, allow_exec, crc);
+  si->init(region, target_base, size, read_only, allow_exec, crc);
 
   if (base != NULL) {
     write_bytes_aligned(base, size);
   }
 }
 
+
+void FileMapInfo::write_bitmap_region(const CHeapBitMap* ptrmap) {
+  ResourceMark rm;
+  size_t size_in_bits = ptrmap->size();
+  size_t size_in_bytes = ptrmap->size_in_bytes();
+  uintptr_t* buffer = (uintptr_t*)NEW_RESOURCE_ARRAY(char, size_in_bytes);
+  ptrmap->write_to(buffer, size_in_bytes);
+  header()->set_ptrmap_size_in_bits(size_in_bits);
+
+  log_info(cds)("ptrmap = " INTPTR_FORMAT " (" SIZE_FORMAT " bytes)",
+                p2i(buffer), size_in_bytes);
+  write_region(MetaspaceShared::bm, (char*)buffer, size_in_bytes, /*read_only=*/true, /*allow_exec=*/false);
+}
+
 // Write out the given archive heap memory regions.  GC code combines multiple
 // consecutive archive GC regions into one MemRegion whenever possible and
 // produces the 'heap_mem' array.
@@ -1229,11 +1252,13 @@
       total_size += size;
     }
 
-    log_info(cds)("Archive heap region %d " INTPTR_FORMAT " - " INTPTR_FORMAT " = " SIZE_FORMAT_W(8) " bytes",
+    log_info(cds)("Archive heap region %d: " INTPTR_FORMAT " - " INTPTR_FORMAT " = " SIZE_FORMAT_W(8) " bytes",
                   i, p2i(start), p2i(start + size), size);
     write_region(i, start, size, false, false);
     if (size > 0) {
-      space_at(i)->init_oopmap(oopmaps->at(arr_idx)._oopmap,
+      address oopmap = oopmaps->at(arr_idx)._oopmap;
+      assert(oopmap >= (address)SharedBaseAddress, "must be");
+      space_at(i)->init_oopmap(oopmap - (address)SharedBaseAddress,
                                oopmaps->at(arr_idx)._oopmap_size_in_bits);
     }
   }
@@ -1285,6 +1310,9 @@
   align_file_position();
 }
 
+void FileMapInfo::set_final_requested_base(char* b) {
+  header()->set_final_requested_base(b);
+}
 
 // Close the shared archive file.  This does NOT unmap mapped regions.
 
@@ -1331,94 +1359,197 @@
   return true;
 }
 
-// Map the whole region at once, assumed to be allocated contiguously.
-ReservedSpace FileMapInfo::reserve_shared_memory() {
-  char* requested_addr = region_addr(0);
-  size_t size = FileMapInfo::core_spaces_size();
-
-  // Reserve the space first, then map otherwise map will go right over some
-  // other reserved memory (like the code cache).
-  ReservedSpace rs(size, os::vm_allocation_granularity(), false, requested_addr);
-  if (!rs.is_reserved()) {
-    fail_continue("Unable to reserve shared space at required address "
-                  INTPTR_FORMAT, p2i(requested_addr));
-    return rs;
-  }
-  // the reserved virtual memory is for mapping class data sharing archive
-  MemTracker::record_virtual_memory_type((address)rs.base(), mtClassShared);
-
-  return rs;
-}
-
 // Memory map a region in the address space.
-static const char* shared_region_name[] = { "MiscData", "ReadWrite", "ReadOnly", "MiscCode",
+static const char* shared_region_name[] = { "MiscData", "ReadWrite", "ReadOnly", "MiscCode", "Bitmap",
                                             "String1", "String2", "OpenArchive1", "OpenArchive2" };
 
-char* FileMapInfo::map_regions(int regions[], char* saved_base[], size_t len) {
-  char* prev_top = NULL;
-  char* curr_base;
-  char* curr_top;
-  int i = 0;
-  for (i = 0; i < (int)len; i++) {
-    curr_base = map_region(regions[i], &curr_top);
-    if (curr_base == NULL) {
-      return NULL;
+MapArchiveResult FileMapInfo::map_regions(int regions[], int num_regions, char* mapped_base_address, ReservedSpace rs) {
+  DEBUG_ONLY(FileMapRegion* last_region = NULL);
+  intx addr_delta = mapped_base_address - header()->requested_base_address();
+
+  // Make sure we don't attempt to use header()->mapped_base_address() unless
+  // it's been successfully mapped.
+  DEBUG_ONLY(header()->set_mapped_base_address((char*)(uintptr_t)0xdeadbeef);)
+
+  for (int r = 0; r < num_regions; r++) {
+    int idx = regions[r];
+    MapArchiveResult result = map_region(idx, addr_delta, mapped_base_address, rs);
+    if (result != MAP_ARCHIVE_SUCCESS) {
+      return result;
     }
-    if (i > 0) {
-      // We require that mc->rw->ro->md to be laid out consecutively, with no
-      // gaps between them. That way, we can ensure that the OS won't be able to
-      // allocate any new memory spaces inside _shared_metaspace_{base,top}, which
-      // would mess up the simple comparision in MetaspaceShared::is_in_shared_metaspace().
-      assert(curr_base == prev_top, "must be");
-    }
-    log_info(cds)("Mapped region #%d at base %p top %p", regions[i], curr_base, curr_top);
-    saved_base[i] = curr_base;
-    prev_top = curr_top;
+    FileMapRegion* si = space_at(idx);
+    DEBUG_ONLY(if (last_region != NULL) {
+        // Ensure that the OS won't be able to allocate new memory spaces between any mapped
+        // regions, or else it would mess up the simple comparision in MetaspaceObj::is_shared().
+        assert(si->mapped_base() == last_region->mapped_end(), "must have no gaps");
+      }
+      last_region = si;)
+    log_info(cds)("Mapped %s region #%d at base " INTPTR_FORMAT " top " INTPTR_FORMAT " (%s)", is_static() ? "static " : "dynamic",
+                  idx, p2i(si->mapped_base()), p2i(si->mapped_end()),
+                  shared_region_name[idx]);
+
   }
-  return curr_top;
+
+  DEBUG_ONLY(if (addr_delta == 0 && ArchiveRelocationMode == 1) {
+      // This is for simulating mmap failures at the requested address. We do it here (instead
+      // of MetaspaceShared::map_archives) so we can thoroughly test the code for failure handling
+      // (releasing all allocated resource, etc).
+      log_info(cds)("ArchiveRelocationMode == 1: always map archive(s) at an alternative address");
+      return MAP_ARCHIVE_MMAP_FAILURE;
+    });
+
+  header()->set_mapped_base_address(header()->requested_base_address() + addr_delta);
+  if (addr_delta != 0 && !relocate_pointers(addr_delta)) {
+    return MAP_ARCHIVE_OTHER_FAILURE;
+  }
+
+  return MAP_ARCHIVE_SUCCESS;
 }
 
-char* FileMapInfo::map_region(int i, char** top_ret) {
+bool FileMapInfo::read_region(int i, char* base, size_t size) {
+  assert(MetaspaceShared::use_windows_memory_mapping(), "used by windows only");
+  FileMapRegion* si = space_at(i);
+  log_info(cds)("Commit %s region #%d at base " INTPTR_FORMAT " top " INTPTR_FORMAT " (%s)%s",
+                is_static() ? "static " : "dynamic", i, p2i(base), p2i(base + size),
+                shared_region_name[i], si->allow_exec() ? " exec" : "");
+  if (!os::commit_memory(base, size, si->allow_exec())) {
+    log_error(cds)("Failed to commit %s region #%d (%s)", is_static() ? "static " : "dynamic",
+                   i, shared_region_name[i]);
+    return false;
+  }
+  if (lseek(_fd, (long)si->file_offset(), SEEK_SET) != (int)si->file_offset() ||
+      read_bytes(base, size) != size) {
+    return false;
+  }
+  return true;
+}
+
+MapArchiveResult FileMapInfo::map_region(int i, intx addr_delta, char* mapped_base_address, ReservedSpace rs) {
   assert(!HeapShared::is_heap_region(i), "sanity");
   FileMapRegion* si = space_at(i);
-  size_t used = si->used();
-  size_t alignment = os::vm_allocation_granularity();
-  size_t size = align_up(used, alignment);
-  char *requested_addr = region_addr(i);
+  size_t size = si->used_aligned();
+  char *requested_addr = mapped_base_address + si->mapping_offset();
+  assert(si->mapped_base() == NULL, "must be not mapped yet");
+  assert(requested_addr != NULL, "must be specified");
+
+  si->set_mapped_from_file(false);
 
-#ifdef _WINDOWS
-  // Windows cannot remap read-only shared memory to read-write when required for
-  // RedefineClasses, which is also used by JFR.  Always map windows regions as RW.
-  si->set_read_only(false);
-#else
-  // If a tool agent is in use (debugging enabled), or JFR, we must map the address space RW
-  if (JvmtiExport::can_modify_any_class() || JvmtiExport::can_walk_any_space() ||
-      Arguments::has_jfr_option()) {
+  if (MetaspaceShared::use_windows_memory_mapping()) {
+    // Windows cannot remap read-only shared memory to read-write when required for
+    // RedefineClasses, which is also used by JFR.  Always map windows regions as RW.
+    si->set_read_only(false);
+  } else if (JvmtiExport::can_modify_any_class() || JvmtiExport::can_walk_any_space() ||
+             Arguments::has_jfr_option()) {
+    // If a tool agent is in use (debugging enabled), or JFR, we must map the address space RW
     si->set_read_only(false);
+  } else if (addr_delta != 0) {
+    si->set_read_only(false); // Need to patch the pointers
+  }
+
+  if (rs.is_reserved()) {
+    assert(rs.contains(requested_addr) && rs.contains(requested_addr + size - 1), "must be");
+    MemTracker::record_virtual_memory_type((address)requested_addr, mtClassShared);
   }
-#endif // _WINDOWS
 
-  // map the contents of the CDS archive in this memory
-  char *base = os::map_memory(_fd, _full_path, si->file_offset(),
-                              requested_addr, size, si->read_only(),
-                              si->allow_exec());
-  if (base == NULL || base != requested_addr) {
-    fail_continue("Unable to map %s shared space at required address.", shared_region_name[i]);
-    _memory_mapping_failed = true;
-    return NULL;
+  if (MetaspaceShared::use_windows_memory_mapping() && addr_delta != 0) {
+    // This is the second time we try to map the archive(s). We have already created a ReservedSpace
+    // that covers all the FileMapRegions to ensure all regions can be mapped. However, Windows
+    // can't mmap into a ReservedSpace, so we just os::read() the data. We're going to patch all the
+    // regions anyway, so there's no benefit for mmap anyway.
+    if (!read_region(i, requested_addr, size)) {
+      return MAP_ARCHIVE_OTHER_FAILURE; // oom or I/O error.
+    }
+  } else {
+    char* base = os::map_memory(_fd, _full_path, si->file_offset(),
+                                requested_addr, size, si->read_only(),
+                                si->allow_exec());
+    if (base != requested_addr) {
+      log_info(cds)("Unable to map %s shared space at required address.", shared_region_name[i]);
+      _memory_mapping_failed = true;
+      return MAP_ARCHIVE_MMAP_FAILURE;
+    }
+    si->set_mapped_from_file(true);
   }
-#ifdef _WINDOWS
-  // This call is Windows-only because the memory_type gets recorded for the other platforms
-  // in method FileMapInfo::reserve_shared_memory(), which is not called on Windows.
-  MemTracker::record_virtual_memory_type((address)base, mtClassShared);
-#endif
+  si->set_mapped_base(requested_addr);
+
+  if (!rs.is_reserved()) {
+    // When mapping on Windows with (addr_delta == 0), we don't reserve the address space for the regions
+    // (Windows can't mmap into a ReservedSpace). In this case, NMT requires we call it after
+    // os::map_memory has succeeded.
+    assert(MetaspaceShared::use_windows_memory_mapping(), "Windows memory mapping only");
+    MemTracker::record_virtual_memory_type((address)requested_addr, mtClassShared);
+  }
 
   if (VerifySharedSpaces && !verify_region_checksum(i)) {
+    return MAP_ARCHIVE_OTHER_FAILURE;
+  }
+
+  return MAP_ARCHIVE_SUCCESS;
+}
+
+char* FileMapInfo::map_relocation_bitmap(size_t& bitmap_size) {
+  FileMapRegion* si = space_at(MetaspaceShared::bm);
+  bitmap_size = si->used_aligned();
+  bool read_only = true, allow_exec = false;
+  char* requested_addr = NULL; // allow OS to pick any location
+  char* bitmap_base = os::map_memory(_fd, _full_path, si->file_offset(),
+                                     requested_addr, bitmap_size, read_only, allow_exec);
+  if (bitmap_base == NULL) {
+    log_error(cds)("failed to map relocation bitmap");
     return NULL;
   }
 
-  *top_ret = base + size;
-  return base;
+  if (VerifySharedSpaces && !region_crc_check(bitmap_base, bitmap_size, si->crc())) {
+    log_error(cds)("relocation bitmap CRC error");
+    if (!os::unmap_memory(bitmap_base, bitmap_size)) {
+      fatal("os::unmap_memory of relocation bitmap failed");
+    }
+    return NULL;
+  }
+
+  return bitmap_base;
+}
+
+bool FileMapInfo::relocate_pointers(intx addr_delta) {
+  log_debug(cds, reloc)("runtime archive relocation start");
+  size_t bitmap_size;
+  char* bitmap_base = map_relocation_bitmap(bitmap_size);
+
+  if (bitmap_base == NULL) {
+    return false;
+  } else {
+    size_t ptrmap_size_in_bits = header()->ptrmap_size_in_bits();
+    log_debug(cds, reloc)("mapped relocation bitmap @ " INTPTR_FORMAT " (" SIZE_FORMAT
+                          " bytes = " SIZE_FORMAT " bits)",
+                          p2i(bitmap_base), bitmap_size, ptrmap_size_in_bits);
+
+    BitMapView ptrmap((BitMap::bm_word_t*)bitmap_base, ptrmap_size_in_bits);
+
+    // Patch all pointers in the the mapped region that are marked by ptrmap.
+    address patch_base = (address)mapped_base();
+    address patch_end  = (address)mapped_end();
+
+    // the current value of the pointers to be patched must be within this
+    // range (i.e., must be between the requesed base address, and the of the current archive).
+    // Note: top archive may point to objects in the base archive, but not the other way around.
+    address valid_old_base = (address)header()->requested_base_address();
+    address valid_old_end  = valid_old_base + mapping_end_offset();
+
+    // after patching, the pointers must point inside this range
+    // (the requested location of the archive, as mapped at runtime).
+    address valid_new_base = (address)header()->mapped_base_address();
+    address valid_new_end  = (address)mapped_end();
+
+    SharedDataRelocator<false> patcher((address*)patch_base, (address*)patch_end, valid_old_base, valid_old_end,
+                                       valid_new_base, valid_new_end, addr_delta);
+    ptrmap.iterate(&patcher);
+
+    if (!os::unmap_memory(bitmap_base, bitmap_size)) {
+      fatal("os::unmap_memory of relocation bitmap failed");
+    }
+    log_debug(cds, reloc)("runtime archive relocation done");
+    return true;
+  }
 }
 
 size_t FileMapInfo::read_bytes(void* buffer, size_t count) {
@@ -1434,10 +1565,13 @@
 }
 
 address FileMapInfo::decode_start_address(FileMapRegion* spc, bool with_current_oop_encoding_mode) {
+  size_t offset = spc->mapping_offset();
+  assert((offset >> 32) == 0, "must be 32-bit only");
+  uint n = (uint)offset;
   if (with_current_oop_encoding_mode) {
-    return (address)CompressedOops::decode_not_null(spc->offset());
+    return (address)CompressedOops::decode_not_null(n);
   } else {
-    return (address)HeapShared::decode_from_archive(spc->offset());
+    return (address)HeapShared::decode_from_archive(n);
   }
 }
 
@@ -1705,7 +1839,7 @@
                                                         int first_region_idx) {
   for (int i=0; i<num_ranges; i++) {
     FileMapRegion* si = space_at(i + first_region_idx);
-    HeapShared::patch_archived_heap_embedded_pointers(ranges[i], (address)si->oopmap(),
+    HeapShared::patch_archived_heap_embedded_pointers(ranges[i], (address)(SharedBaseAddress + si->oopmap_offset()),
                                                       si->oopmap_size_in_bits());
   }
 }
@@ -1759,11 +1893,10 @@
   }
 }
 
-void FileMapInfo::unmap_regions(int regions[], char* saved_base[], size_t len) {
-  for (int i = 0; i < (int)len; i++) {
-    if (saved_base[i] != NULL) {
-      unmap_region(regions[i]);
-    }
+void FileMapInfo::unmap_regions(int regions[], int num_regions) {
+  for (int r = 0; r < num_regions; r++) {
+    int idx = regions[r];
+    unmap_region(idx);
   }
 }
 
@@ -1772,16 +1905,17 @@
 void FileMapInfo::unmap_region(int i) {
   assert(!HeapShared::is_heap_region(i), "sanity");
   FileMapRegion* si = space_at(i);
+  char* mapped_base = si->mapped_base();
   size_t used = si->used();
   size_t size = align_up(used, os::vm_allocation_granularity());
 
-  if (used == 0) {
-    return;
-  }
-
-  char* addr = region_addr(i);
-  if (!os::unmap_memory(addr, size)) {
-    fail_stop("Unable to unmap shared space.");
+  if (mapped_base != NULL && size > 0 && si->mapped_from_file()) {
+    log_info(cds)("Unmapping region #%d at base " INTPTR_FORMAT " (%s)", i, p2i(mapped_base),
+                  shared_region_name[i]);
+    if (!os::unmap_memory(mapped_base, size)) {
+      fatal("os::unmap_memory failed");
+    }
+    si->set_mapped_base(NULL);
   }
 }
 
@@ -1813,7 +1947,7 @@
 // [1] validate_header() - done here.
 // [2] validate_shared_path_table - this is done later, because the table is in the RW
 //     region of the archive, which is not mapped yet.
-bool FileMapInfo::initialize(bool is_static) {
+bool FileMapInfo::initialize() {
   assert(UseSharedSpaces, "UseSharedSpaces expected.");
 
   if (JvmtiExport::should_post_class_file_load_hook() && JvmtiExport::has_early_class_hook_env()) {
@@ -1828,11 +1962,10 @@
   if (!open_for_read()) {
     return false;
   }
-
-  init_from_file(_fd, is_static);
-  // UseSharedSpaces could be disabled if the checking of some of the header fields in
-  // init_from_file has failed.
-  if (!UseSharedSpaces || !validate_header(is_static)) {
+  if (!init_from_file(_fd)) {
+    return false;
+  }
+  if (!validate_header()) {
     return false;
   }
   return true;
@@ -1845,10 +1978,18 @@
     return si->used() > 0 ?
           (char*)start_address_as_decoded_with_current_oop_encoding_mode(si) : NULL;
   } else {
-    return si->base();
+    return si->mapped_base();
   }
 }
 
+FileMapRegion* FileMapInfo::first_core_space() const {
+  return is_static() ? space_at(MetaspaceShared::mc) : space_at(MetaspaceShared::rw);
+}
+
+FileMapRegion* FileMapInfo::last_core_space() const {
+  return is_static() ? space_at(MetaspaceShared::md) : space_at(MetaspaceShared::mc);
+}
+
 int FileMapHeader::compute_crc() {
   char* start = (char*)this;
   // start computing from the field after _crc
@@ -1860,7 +2001,6 @@
 
 // This function should only be called during run time with UseSharedSpaces enabled.
 bool FileMapHeader::validate() {
-
   if (_obj_alignment != ObjectAlignmentInBytes) {
     FileMapInfo::fail_continue("The shared archive file's ObjectAlignmentInBytes of %d"
                   " does not equal the current ObjectAlignmentInBytes of " INTX_FORMAT ".",
@@ -1913,7 +2053,7 @@
   return true;
 }
 
-bool FileMapInfo::validate_header(bool is_static) {
+bool FileMapInfo::validate_header() {
   return header()->validate();
 }
 
@@ -1932,18 +2072,14 @@
 
 // Unmap mapped regions of shared space.
 void FileMapInfo::stop_sharing_and_unmap(const char* msg) {
-  MetaspaceShared::set_shared_metaspace_range(NULL, NULL);
+  MetaspaceShared::set_shared_metaspace_range(NULL, NULL, NULL);
 
   FileMapInfo *map_info = FileMapInfo::current_info();
   if (map_info) {
     map_info->fail_continue("%s", msg);
     for (int i = 0; i < MetaspaceShared::num_non_heap_spaces; i++) {
       if (!HeapShared::is_heap_region(i)) {
-        char *addr = map_info->region_addr(i);
-        if (addr != NULL) {
-          map_info->unmap_region(i);
-          map_info->space_at(i)->mark_invalid();
-        }
+        map_info->unmap_region(i);
       }
     }
     // Dealloc the archive heap regions only without unmapping. The regions are part
--- a/src/hotspot/share/memory/filemap.hpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/memory/filemap.hpp	Wed Nov 13 16:36:54 2019 -0800
@@ -43,6 +43,8 @@
 
 static const int JVM_IDENT_MAX = 256;
 
+class CHeapBitMap;
+
 class SharedClassPathEntry {
   enum {
     modules_image_entry,
@@ -104,6 +106,9 @@
   Array<u8>* _table;
   int _size;
 public:
+  SharedPathTable() : _table(NULL), _size(0) {}
+  SharedPathTable(Array<u8>* table, int size) : _table(table), _size(size) {}
+
   void dumptime_init(ClassLoaderData* loader_data, Thread* THREAD);
   void metaspace_pointers_do(MetaspaceClosure* it);
 
@@ -138,25 +143,29 @@
   }
 
   // Accessors
-  int crc()                      const { return _crc; }
-  size_t file_offset()           const { return _file_offset; }
-  char*  base()                  const { assert_is_not_heap_region(); return _addr._base;  }
-  narrowOop offset()             const { assert_is_heap_region();     return (narrowOop)(_addr._offset); }
-  size_t used()                  const { return _used; }
-  bool read_only()               const { return _read_only != 0; }
-  bool allow_exec()              const { return _allow_exec != 0; }
-  void* oopmap()                 const { return _oopmap; }
-  size_t oopmap_size_in_bits()   const { return _oopmap_size_in_bits; }
+  int crc()                         const { return _crc; }
+  size_t file_offset()              const { return _file_offset; }
+  size_t mapping_offset()           const { return _mapping_offset; }
+  size_t mapping_end_offset()       const { return _mapping_offset + used_aligned(); }
+  size_t used()                     const { return _used; }
+  size_t used_aligned()             const; // aligned up to os::vm_allocation_granularity()
+  char*  mapped_base()              const { assert_is_not_heap_region(); return _mapped_base; }
+  char*  mapped_end()               const { return mapped_base()        + used_aligned(); }
+  bool   read_only()                const { return _read_only != 0; }
+  bool   allow_exec()               const { return _allow_exec != 0; }
+  bool   mapped_from_file()         const { return _mapped_from_file != 0; }
+  size_t oopmap_offset()            const { assert_is_heap_region();     return _oopmap_offset; }
+  size_t oopmap_size_in_bits()      const { assert_is_heap_region();     return _oopmap_size_in_bits; }
 
-  void set_file_offset(size_t s) { _file_offset = s; }
-  void set_read_only(bool v)     { _read_only = v; }
-  void mark_invalid()            { _addr._base = NULL; }
-
-  void init(bool is_heap_region, char* base, size_t size, bool read_only,
+  void set_file_offset(size_t s)     { _file_offset = s; }
+  void set_read_only(bool v)         { _read_only = v; }
+  void set_mapped_base(char* p)      { _mapped_base = p; }
+  void set_mapped_from_file(bool v)  { _mapped_from_file = v; }
+  void init(int region_index, char* base, size_t size, bool read_only,
             bool allow_exec, int crc);
 
-  void init_oopmap(void* map, size_t size_in_bits) {
-    _oopmap = map;
+  void init_oopmap(size_t oopmap_offset, size_t size_in_bits) {
+    _oopmap_offset = oopmap_offset;
     _oopmap_size_in_bits = size_in_bits;
   }
 };
@@ -178,13 +187,10 @@
   uintx  _max_heap_size;            // java max heap size during dumping
   CompressedOops::Mode _narrow_oop_mode; // compressed oop encoding mode
   int     _narrow_klass_shift;      // save narrow klass base and shift
-  address _narrow_klass_base;
-  char*   _misc_data_patching_start;
-  char*   _serialized_data_start;  // Data accessed using {ReadClosure,WriteClosure}::serialize()
-  address _i2i_entry_code_buffers;
+  size_t  _misc_data_patching_offset;
+  size_t  _serialized_data_offset;  // Data accessed using {ReadClosure,WriteClosure}::serialize()
+  size_t  _i2i_entry_code_buffers_offset;
   size_t  _i2i_entry_code_buffers_size;
-  size_t  _core_spaces_size;        // number of bytes allocated by the core spaces
-                                    // (mc, md, ro, rw and od).
   address _heap_end;                // heap end at dump time.
   bool _base_archive_is_default;    // indicates if the base archive is the system default one
 
@@ -202,7 +208,8 @@
   //      check_nonempty_dir_in_shared_path_table()
   //      validate_shared_path_table()
   //      validate_non_existent_class_paths()
-  SharedPathTable _shared_path_table;
+  size_t _shared_path_table_offset;
+  int    _shared_path_table_size;
 
   jshort _app_class_paths_start_index;  // Index of first app classpath entry
   jshort _app_module_paths_start_index; // Index of first module path entry
@@ -211,9 +218,19 @@
   bool   _verify_local;                 // BytecodeVerificationLocal setting
   bool   _verify_remote;                // BytecodeVerificationRemote setting
   bool   _has_platform_or_app_classes;  // Archive contains app classes
-  size_t _shared_base_address;          // SharedBaseAddress used at dump time
+  char*  _requested_base_address;       // Archive relocation is not necessary if we map with this base address.
+  char*  _mapped_base_address;          // Actual base address where archive is mapped.
+
   bool   _allow_archiving_with_java_agent; // setting of the AllowArchivingWithJavaAgent option
+  size_t _ptrmap_size_in_bits;          // Size of pointer relocation bitmap
 
+  char* from_mapped_offset(size_t offset) const {
+    return mapped_base_address() + offset;
+  }
+  void set_mapped_offset(char* p, size_t *offset) {
+    assert(p >= mapped_base_address(), "sanity");
+    *offset = p - mapped_base_address();
+  }
 public:
   // Accessors -- fields declared in CDSFileMapHeaderBase
   unsigned int magic() const {return _magic;}
@@ -234,19 +251,19 @@
   uintx max_heap_size()                    const { return _max_heap_size; }
   CompressedOops::Mode narrow_oop_mode()   const { return _narrow_oop_mode; }
   int narrow_klass_shift()                 const { return _narrow_klass_shift; }
-  address narrow_klass_base()              const { return _narrow_klass_base; }
-  char* misc_data_patching_start()         const { return _misc_data_patching_start; }
-  char* serialized_data_start()            const { return _serialized_data_start; }
-  address i2i_entry_code_buffers()         const { return _i2i_entry_code_buffers; }
+  address narrow_klass_base()              const { return (address)mapped_base_address(); }
+  char* misc_data_patching_start()         const { return from_mapped_offset(_misc_data_patching_offset); }
+  char* serialized_data_start()            const { return from_mapped_offset(_serialized_data_offset); }
+  address i2i_entry_code_buffers()         const { return (address)from_mapped_offset(_i2i_entry_code_buffers_offset); }
   size_t i2i_entry_code_buffers_size()     const { return _i2i_entry_code_buffers_size; }
-  size_t core_spaces_size()                const { return _core_spaces_size; }
   address heap_end()                       const { return _heap_end; }
   bool base_archive_is_default()           const { return _base_archive_is_default; }
   const char* jvm_ident()                  const { return _jvm_ident; }
   size_t base_archive_name_size()          const { return _base_archive_name_size; }
-  size_t shared_base_address()             const { return _shared_base_address; }
+  char* requested_base_address()           const { return _requested_base_address; }
+  char* mapped_base_address()              const { return _mapped_base_address; }
   bool has_platform_or_app_classes()       const { return _has_platform_or_app_classes; }
-  SharedPathTable shared_path_table()      const { return _shared_path_table; }
+  size_t ptrmap_size_in_bits()             const { return _ptrmap_size_in_bits; }
 
   // FIXME: These should really return int
   jshort max_used_path_index()             const { return _max_used_path_index; }
@@ -254,27 +271,32 @@
   jshort app_class_paths_start_index()     const { return _app_class_paths_start_index; }
   jshort num_module_paths()                const { return _num_module_paths; }
 
-  void set_core_spaces_size(size_t s)            { _core_spaces_size = s; }
   void set_has_platform_or_app_classes(bool v)   { _has_platform_or_app_classes = v; }
-  void set_misc_data_patching_start(char* p)     { _misc_data_patching_start = p; }
-  void set_serialized_data_start(char* p)        { _serialized_data_start   = p; }
+  void set_misc_data_patching_start(char* p)     { set_mapped_offset(p, &_misc_data_patching_offset); }
+  void set_serialized_data_start(char* p)        { set_mapped_offset(p, &_serialized_data_offset); }
   void set_base_archive_name_size(size_t s)      { _base_archive_name_size = s; }
   void set_base_archive_is_default(bool b)       { _base_archive_is_default = b; }
   void set_header_size(size_t s)                 { _header_size = s; }
-
+  void set_ptrmap_size_in_bits(size_t s)         { _ptrmap_size_in_bits = s; }
+  void set_mapped_base_address(char* p)          { _mapped_base_address = p; }
   void set_i2i_entry_code_buffers(address p, size_t s) {
-    _i2i_entry_code_buffers = p;
+    set_mapped_offset((char*)p, &_i2i_entry_code_buffers_offset);
     _i2i_entry_code_buffers_size = s;
   }
 
-  void relocate_shared_path_table(Array<u8>* t) {
-    assert(DynamicDumpSharedSpaces, "only");
-    _shared_path_table.set_table(t);
+  void set_shared_path_table(SharedPathTable table) {
+    set_mapped_offset((char*)table.table(), &_shared_path_table_offset);
+    _shared_path_table_size = table.size();
   }
 
-  void shared_path_table_metaspace_pointers_do(MetaspaceClosure* it) {
-    assert(DynamicDumpSharedSpaces, "only");
-    _shared_path_table.metaspace_pointers_do(it);
+  void set_final_requested_base(char* b) {
+    _requested_base_address = b;
+    _mapped_base_address = 0;
+  }
+
+  SharedPathTable shared_path_table() const {
+    return SharedPathTable((Array<u8>*)from_mapped_offset(_shared_path_table_offset),
+                           _shared_path_table_size);
   }
 
   bool validate();
@@ -301,6 +323,7 @@
 
   bool           _is_static;
   bool           _file_open;
+  bool           _is_mapped;
   int            _fd;
   size_t         _file_offset;
   const char*    _full_path;
@@ -327,8 +350,11 @@
   static bool get_base_archive_name_from_header(const char* archive_name,
                                                 int* size, char** base_archive_name);
   static bool check_archive(const char* archive_name, bool is_static);
+  static SharedPathTable shared_path_table() {
+    return _shared_path_table;
+  }
   void restore_shared_path_table();
-  bool init_from_file(int fd, bool is_static);
+  bool init_from_file(int fd);
   static void metaspace_pointers_do(MetaspaceClosure* it);
 
   void log_paths(const char* msg, int start_idx, int end_idx);
@@ -341,7 +367,7 @@
   void   set_header_crc(int crc)     { header()->set_crc(crc); }
   int    space_crc(int i)      const { return space_at(i)->crc(); }
   void   populate_header(size_t alignment);
-  bool   validate_header(bool is_static);
+  bool   validate_header();
   void   invalidate();
   int    crc()                 const { return header()->crc(); }
   int    version()             const { return header()->version(); }
@@ -370,11 +396,17 @@
     header()->set_i2i_entry_code_buffers(addr, s);
   }
 
-  void set_core_spaces_size(size_t s)         const { header()->set_core_spaces_size(s); }
-  size_t core_spaces_size()                   const { return header()->core_spaces_size(); }
+  bool is_static()                            const { return _is_static; }
+  bool is_mapped()                            const { return _is_mapped; }
+  void set_is_mapped(bool v)                        { _is_mapped = v; }
+  const char* full_path()                     const { return _full_path; }
+  void set_final_requested_base(char* b);
+
+  char* requested_base_address()           const { return header()->requested_base_address(); }
+
 
   class DynamicArchiveHeader* dynamic_header() const {
-    assert(!_is_static, "must be");
+    assert(!is_static(), "must be");
     return (DynamicArchiveHeader*)header();
   }
 
@@ -402,21 +434,21 @@
   static void assert_mark(bool check);
 
   // File manipulation.
-  bool  initialize(bool is_static) NOT_CDS_RETURN_(false);
-  bool  open_for_read(const char* path = NULL);
+  bool  initialize() NOT_CDS_RETURN_(false);
+  bool  open_for_read();
   void  open_for_write(const char* path = NULL);
   void  write_header();
   void  write_region(int region, char* base, size_t size,
                      bool read_only, bool allow_exec);
+  void  write_bitmap_region(const CHeapBitMap* ptrmap);
   size_t write_archive_heap_regions(GrowableArray<MemRegion> *heap_mem,
                                     GrowableArray<ArchiveHeapOopmapInfo> *oopmaps,
                                     int first_region_id, int max_num_regions);
   void  write_bytes(const void* buffer, size_t count);
   void  write_bytes_aligned(const void* buffer, size_t count);
   size_t  read_bytes(void* buffer, size_t count);
-  char* map_regions(int regions[], char* saved_base[], size_t len);
-  char* map_region(int i, char** top_ret);
-  void  map_heap_regions_impl() NOT_CDS_JAVA_HEAP_RETURN;
+  MapArchiveResult map_regions(int regions[], int num_regions, char* mapped_base_address, ReservedSpace rs);
+  void  unmap_regions(int regions[], int num_regions);
   void  map_heap_regions() NOT_CDS_JAVA_HEAP_RETURN;
   void  fixup_mapped_heap_regions() NOT_CDS_JAVA_HEAP_RETURN;
   void  patch_archived_heap_embedded_pointers() NOT_CDS_JAVA_HEAP_RETURN;
@@ -424,7 +456,6 @@
                                               int first_region_idx) NOT_CDS_JAVA_HEAP_RETURN;
   bool  has_heap_regions()  NOT_CDS_JAVA_HEAP_RETURN_(false);
   MemRegion get_heap_regions_range_with_current_oop_encoding_mode() NOT_CDS_JAVA_HEAP_RETURN_(MemRegion());
-  void  unmap_regions(int regions[], char* saved_base[], size_t len);
   void  unmap_region(int i);
   bool  verify_region_checksum(int i);
   void  close();
@@ -452,6 +483,9 @@
   static void check_nonempty_dir_in_shared_path_table();
   bool validate_shared_path_table();
   void validate_non_existent_class_paths();
+  static void set_shared_path_table(FileMapInfo* info) {
+    _shared_path_table = info->header()->shared_path_table();
+  }
   static void update_jar_manifest(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS);
   static int num_non_existent_class_paths();
   static void record_non_existent_class_path_entry(const char* path);
@@ -475,12 +509,28 @@
 
   char* region_addr(int idx);
 
+  // The offset of the first core region in the archive, relative to SharedBaseAddress
+  size_t mapping_base_offset() const { return first_core_space()->mapping_offset(); }
+  // The offset of the (exclusive) end of the last core region in this archive, relative to SharedBaseAddress
+  size_t mapping_end_offset()  const { return last_core_space()->mapping_end_offset(); }
+
+  char* mapped_base()    const { return first_core_space()->mapped_base(); }
+  char* mapped_end()     const { return last_core_space()->mapped_end();   }
+
+  // Non-zero if the archive needs to be mapped a non-default location due to ASLR.
+  intx relocation_delta() const {
+    return header()->mapped_base_address() - header()->requested_base_address();
+  }
+
+  FileMapRegion* first_core_space() const;
+  FileMapRegion* last_core_space() const;
+
  private:
   void  seek_to_position(size_t pos);
   char* skip_first_path_entry(const char* path) NOT_CDS_RETURN_(NULL);
   int   num_paths(const char* path) NOT_CDS_RETURN_(0);
   GrowableArray<const char*>* create_path_array(const char* path) NOT_CDS_RETURN_(NULL);
-  bool  fail(const char* msg, const char* name) NOT_CDS_RETURN_(false);
+  bool  classpath_failure(const char* msg, const char* name) NOT_CDS_RETURN_(false);
   bool  check_paths(int shared_path_start_idx, int num_paths,
                     GrowableArray<const char*>* rp_array) NOT_CDS_RETURN_(false);
   bool  validate_boot_class_paths() NOT_CDS_RETURN_(false);
@@ -489,6 +539,11 @@
                       bool is_open = false) NOT_CDS_JAVA_HEAP_RETURN_(false);
   bool  region_crc_check(char* buf, size_t size, int expected_crc) NOT_CDS_RETURN_(false);
   void  dealloc_archive_heap_regions(MemRegion* regions, int num, bool is_open) NOT_CDS_JAVA_HEAP_RETURN;
+  void  map_heap_regions_impl() NOT_CDS_JAVA_HEAP_RETURN;
+  char* map_relocation_bitmap(size_t& bitmap_size);
+  MapArchiveResult map_region(int i, intx addr_delta, char* mapped_base_address, ReservedSpace rs);
+  bool  read_region(int i, char* base, size_t size);
+  bool  relocate_pointers(intx addr_delta);
 
   FileMapRegion* space_at(int i) const {
     return header()->space_at(i);
--- a/src/hotspot/share/memory/heapShared.cpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/memory/heapShared.cpp	Wed Nov 13 16:36:54 2019 -0800
@@ -26,15 +26,18 @@
 #include "classfile/javaClasses.inline.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/symbolTable.hpp"
+#include "classfile/systemDictionaryShared.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "logging/log.hpp"
 #include "logging/logMessage.hpp"
 #include "logging/logStream.hpp"
+#include "memory/archiveUtils.hpp"
 #include "memory/filemap.hpp"
 #include "memory/heapShared.inline.hpp"
 #include "memory/iterator.inline.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/metaspaceClosure.hpp"
+#include "memory/metaspaceShared.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.hpp"
 #include "oops/compressedOops.inline.hpp"
@@ -383,8 +386,13 @@
           _k->external_name(), i, subgraph_k->external_name());
       }
       _subgraph_object_klasses->at_put(i, subgraph_k);
+      ArchivePtrMarker::mark_pointer(_subgraph_object_klasses->adr_at(i));
     }
   }
+
+  ArchivePtrMarker::mark_pointer(&_k);
+  ArchivePtrMarker::mark_pointer(&_entry_field_records);
+  ArchivePtrMarker::mark_pointer(&_subgraph_object_klasses);
 }
 
 struct CopyKlassSubGraphInfoToArchive : StackObj {
@@ -397,7 +405,7 @@
         (ArchivedKlassSubGraphInfoRecord*)MetaspaceShared::read_only_space_alloc(sizeof(ArchivedKlassSubGraphInfoRecord));
       record->init(&info);
 
-      unsigned int hash = primitive_hash<Klass*>(klass);
+      unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary(klass);
       u4 delta = MetaspaceShared::object_delta_u4(record);
       _writer->add(hash, delta);
     }
@@ -436,7 +444,7 @@
   }
   assert(!DumpSharedSpaces, "Should not be called with DumpSharedSpaces");
 
-  unsigned int hash = primitive_hash<Klass*>(k);
+  unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary(k);
   const ArchivedKlassSubGraphInfoRecord* record = _run_time_subgraph_info_table.lookup(k, hash, 0);
 
   // Initialize from archived data. Currently this is done only
@@ -606,8 +614,20 @@
   assert(orig_obj != NULL, "must be");
   assert(!is_archived_object(orig_obj), "sanity");
 
-  // java.lang.Class instances cannot be included in an archived
-  // object sub-graph.
+  if (!JavaClasses::is_supported_for_archiving(orig_obj)) {
+    // This object has injected fields that cannot be supported easily, so we disallow them for now.
+    // If you get an error here, you probably made a change in the JDK library that has added
+    // these objects that are referenced (directly or indirectly) by static fields.
+    ResourceMark rm;
+    log_error(cds, heap)("Cannot archive object of class %s", orig_obj->klass()->external_name());
+    vm_exit(1);
+  }
+
+  // java.lang.Class instances cannot be included in an archived object sub-graph. We only support
+  // them as Klass::_archived_mirror because they need to be specially restored at run time.
+  //
+  // If you get an error here, you probably made a change in the JDK library that has added a Class
+  // object that is referenced (directly or indirectly) by static fields.
   if (java_lang_Class::is_instance(orig_obj)) {
     log_error(cds, heap)("(%d) Unknown java.lang.Class object is in the archived sub-graph", level);
     vm_exit(1);
--- a/src/hotspot/share/memory/metaspace.cpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/memory/metaspace.cpp	Wed Nov 13 16:36:54 2019 -0800
@@ -975,25 +975,18 @@
 #ifdef _LP64
 static const uint64_t UnscaledClassSpaceMax = (uint64_t(max_juint) + 1);
 
-void Metaspace::set_narrow_klass_base_and_shift(address metaspace_base, address cds_base) {
+void Metaspace::set_narrow_klass_base_and_shift(ReservedSpace metaspace_rs, address cds_base) {
   assert(!DumpSharedSpaces, "narrow_klass is set by MetaspaceShared class.");
   // Figure out the narrow_klass_base and the narrow_klass_shift.  The
   // narrow_klass_base is the lower of the metaspace base and the cds base
   // (if cds is enabled).  The narrow_klass_shift depends on the distance
   // between the lower base and higher address.
-  address lower_base;
-  address higher_address;
-#if INCLUDE_CDS
-  if (UseSharedSpaces) {
-    higher_address = MAX2((address)(cds_base + MetaspaceShared::core_spaces_size()),
-                          (address)(metaspace_base + compressed_class_space_size()));
-    lower_base = MIN2(metaspace_base, cds_base);
-  } else
-#endif
-  {
-    higher_address = metaspace_base + compressed_class_space_size();
-    lower_base = metaspace_base;
-
+  address lower_base = (address)metaspace_rs.base();
+  address higher_address = (address)metaspace_rs.end();
+  if (cds_base != NULL) {
+    assert(UseSharedSpaces, "must be");
+    lower_base = MIN2(lower_base, cds_base);
+  } else {
     uint64_t klass_encoding_max = UnscaledClassSpaceMax << LogKlassAlignmentInBytes;
     // If compressed class space fits in lower 32G, we don't need a base.
     if (higher_address <= (address)klass_encoding_max) {
@@ -1018,21 +1011,8 @@
   AOTLoader::set_narrow_klass_shift();
 }
 
-#if INCLUDE_CDS
-// Return TRUE if the specified metaspace_base and cds_base are close enough
-// to work with compressed klass pointers.
-bool Metaspace::can_use_cds_with_metaspace_addr(char* metaspace_base, address cds_base) {
-  assert(cds_base != 0 && UseSharedSpaces, "Only use with CDS");
-  assert(UseCompressedClassPointers, "Only use with CompressedKlassPtrs");
-  address lower_base = MIN2((address)metaspace_base, cds_base);
-  address higher_address = MAX2((address)(cds_base + MetaspaceShared::core_spaces_size()),
-                                (address)(metaspace_base + compressed_class_space_size()));
-  return ((uint64_t)(higher_address - lower_base) <= UnscaledClassSpaceMax);
-}
-#endif
-
 // Try to allocate the metaspace at the requested addr.
-void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, address cds_base) {
+void Metaspace::allocate_metaspace_compressed_klass_ptrs(ReservedSpace metaspace_rs, char* requested_addr, address cds_base) {
   assert(!DumpSharedSpaces, "compress klass space is allocated by MetaspaceShared class.");
   assert(using_class_space(), "called improperly");
   assert(UseCompressedClassPointers, "Only use with CompressedKlassPtrs");
@@ -1045,14 +1025,16 @@
   // Don't use large pages for the class space.
   bool large_pages = false;
 
+ if (metaspace_rs.is_reserved()) {
+   // CDS should have already reserved the space.
+   assert(requested_addr == NULL, "not used");
+   assert(cds_base != NULL, "CDS should have already reserved the memory space");
+ } else {
+   assert(cds_base == NULL, "must be");
 #if !(defined(AARCH64) || defined(AIX))
-  ReservedSpace metaspace_rs = ReservedSpace(compressed_class_space_size(),
-                                             _reserve_alignment,
-                                             large_pages,
-                                             requested_addr);
+  metaspace_rs = ReservedSpace(compressed_class_space_size(), _reserve_alignment,
+                               large_pages, requested_addr);
 #else // AARCH64
-  ReservedSpace metaspace_rs;
-
   // Our compressed klass pointers may fit nicely into the lower 32
   // bits.
   if ((uint64_t)requested_addr + compressed_class_space_size() < 4*G) {
@@ -1077,19 +1059,6 @@
         increment = 4*G;
       }
 
-#if INCLUDE_CDS
-      if (UseSharedSpaces
-          && ! can_use_cds_with_metaspace_addr(a, cds_base)) {
-        // We failed to find an aligned base that will reach.  Fall
-        // back to using our requested addr.
-        metaspace_rs = ReservedSpace(compressed_class_space_size(),
-                                     _reserve_alignment,
-                                     large_pages,
-                                     requested_addr);
-        break;
-      }
-#endif
-
       metaspace_rs = ReservedSpace(compressed_class_space_size(),
                                    _reserve_alignment,
                                    large_pages,
@@ -1098,53 +1067,30 @@
         break;
     }
   }
-
 #endif // AARCH64
+ }
 
   if (!metaspace_rs.is_reserved()) {
-#if INCLUDE_CDS
-    if (UseSharedSpaces) {
-      size_t increment = align_up(1*G, _reserve_alignment);
-
-      // Keep trying to allocate the metaspace, increasing the requested_addr
-      // by 1GB each time, until we reach an address that will no longer allow
-      // use of CDS with compressed klass pointers.
-      char *addr = requested_addr;
-      while (!metaspace_rs.is_reserved() && (addr + increment > addr) &&
-             can_use_cds_with_metaspace_addr(addr + increment, cds_base)) {
-        addr = addr + increment;
-        metaspace_rs = ReservedSpace(compressed_class_space_size(),
-                                     _reserve_alignment, large_pages, addr);
-      }
-    }
-#endif
+    assert(cds_base == NULL, "CDS should have already reserved the memory space");
     // If no successful allocation then try to allocate the space anywhere.  If
     // that fails then OOM doom.  At this point we cannot try allocating the
     // metaspace as if UseCompressedClassPointers is off because too much
     // initialization has happened that depends on UseCompressedClassPointers.
     // So, UseCompressedClassPointers cannot be turned off at this point.
+    metaspace_rs = ReservedSpace(compressed_class_space_size(),
+                                 _reserve_alignment, large_pages);
     if (!metaspace_rs.is_reserved()) {
-      metaspace_rs = ReservedSpace(compressed_class_space_size(),
-                                   _reserve_alignment, large_pages);
-      if (!metaspace_rs.is_reserved()) {
-        vm_exit_during_initialization(err_msg("Could not allocate metaspace: " SIZE_FORMAT " bytes",
-                                              compressed_class_space_size()));
-      }
+      vm_exit_during_initialization(err_msg("Could not allocate metaspace: " SIZE_FORMAT " bytes",
+                                            compressed_class_space_size()));
     }
   }
 
-  // If we got here then the metaspace got allocated.
-  MemTracker::record_virtual_memory_type((address)metaspace_rs.base(), mtClass);
+  if (cds_base == NULL) {
+    // If we got here then the metaspace got allocated.
+    MemTracker::record_virtual_memory_type((address)metaspace_rs.base(), mtClass);
+  }
 
-#if INCLUDE_CDS
-  // Verify that we can use shared spaces.  Otherwise, turn off CDS.
-  if (UseSharedSpaces && !can_use_cds_with_metaspace_addr(metaspace_rs.base(), cds_base)) {
-    FileMapInfo::stop_sharing_and_unmap(
-        "Could not allocate metaspace at a compatible address");
-  }
-#endif
-  set_narrow_klass_base_and_shift((address)metaspace_rs.base(),
-                                  UseSharedSpaces ? (address)cds_base : 0);
+  set_narrow_klass_base_and_shift(metaspace_rs, cds_base);
 
   initialize_class_space(metaspace_rs);
 
@@ -1247,31 +1193,30 @@
 void Metaspace::global_initialize() {
   MetaspaceGC::initialize();
 
+  bool class_space_inited = false;
 #if INCLUDE_CDS
   if (DumpSharedSpaces) {
     MetaspaceShared::initialize_dumptime_shared_and_meta_spaces();
+    class_space_inited = true;
   } else if (UseSharedSpaces) {
     // If any of the archived space fails to map, UseSharedSpaces
-    // is reset to false. Fall through to the
-    // (!DumpSharedSpaces && !UseSharedSpaces) case to set up class
-    // metaspace.
+    // is reset to false.
     MetaspaceShared::initialize_runtime_shared_and_meta_spaces();
+    class_space_inited = UseSharedSpaces;
   }
 
   if (DynamicDumpSharedSpaces && !UseSharedSpaces) {
     vm_exit_during_initialization("DynamicDumpSharedSpaces is unsupported when base CDS archive is not loaded", NULL);
   }
+#endif // INCLUDE_CDS
 
-  if (!DumpSharedSpaces && !UseSharedSpaces)
-#endif // INCLUDE_CDS
-  {
 #ifdef _LP64
-    if (using_class_space()) {
-      char* base = (char*)align_up(CompressedOops::end(), _reserve_alignment);
-      allocate_metaspace_compressed_klass_ptrs(base, 0);
-    }
-#endif // _LP64
+  if (using_class_space() && !class_space_inited) {
+    char* base = (char*)align_up(CompressedOops::end(), _reserve_alignment);
+    ReservedSpace dummy;
+    allocate_metaspace_compressed_klass_ptrs(dummy, base, 0);
   }
+#endif
 
   // Initialize these before initializing the VirtualSpaceList
   _first_chunk_word_size = InitialBootClassLoaderMetaspaceSize / BytesPerWord;
--- a/src/hotspot/share/memory/metaspace.hpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/memory/metaspace.hpp	Wed Nov 13 16:36:54 2019 -0800
@@ -172,16 +172,13 @@
     assert(!_frozen, "sanity");
   }
 #ifdef _LP64
-  static void allocate_metaspace_compressed_klass_ptrs(char* requested_addr, address cds_base);
+  static void allocate_metaspace_compressed_klass_ptrs(ReservedSpace metaspace_rs, char* requested_addr, address cds_base);
 #endif
 
  private:
 
 #ifdef _LP64
-  static void set_narrow_klass_base_and_shift(address metaspace_base, address cds_base);
-
-  // Returns true if can use CDS with metaspace allocated as specified address.
-  static bool can_use_cds_with_metaspace_addr(char* metaspace_base, address cds_base);
+  static void set_narrow_klass_base_and_shift(ReservedSpace metaspace_rs, address cds_base);
 
   static void initialize_class_space(ReservedSpace rs);
 #endif
--- a/src/hotspot/share/memory/metaspaceClosure.hpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/memory/metaspaceClosure.hpp	Wed Nov 13 16:36:54 2019 -0800
@@ -75,6 +75,10 @@
     _default
   };
 
+  enum SpecialRef {
+    _method_entry_ref
+  };
+
   // class MetaspaceClosure::Ref --
   //
   // MetaspaceClosure can be viewed as a very simple type of copying garbage
@@ -278,6 +282,16 @@
   template <class T> void push(T** mpp, Writability w = _default) {
     push_impl(new ObjectRef<T>(mpp, w));
   }
+
+  template <class T> void push_method_entry(T** mpp, intptr_t* p) {
+    push_special(_method_entry_ref, new ObjectRef<T>(mpp, _default), (intptr_t*)p);
+  }
+
+  // This is for tagging special pointers that are not a reference to MetaspaceObj. It's currently
+  // used to mark the method entry points in Method/ConstMethod.
+  virtual void push_special(SpecialRef type, Ref* obj, intptr_t* p) {
+    assert(type == _method_entry_ref, "only special type allowed for now");
+  }
 };
 
 // This is a special MetaspaceClosure that visits each unique MetaspaceObj once.
--- a/src/hotspot/share/memory/metaspaceShared.cpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/memory/metaspaceShared.cpp	Wed Nov 13 16:36:54 2019 -0800
@@ -41,6 +41,8 @@
 #include "interpreter/bytecodes.hpp"
 #include "logging/log.hpp"
 #include "logging/logMessage.hpp"
+#include "memory/archiveUtils.inline.hpp"
+#include "memory/dynamicArchive.hpp"
 #include "memory/filemap.hpp"
 #include "memory/heapShared.inline.hpp"
 #include "memory/metaspace.hpp"
@@ -48,7 +50,6 @@
 #include "memory/metaspaceShared.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.hpp"
-#include "memory/dynamicArchive.hpp"
 #include "oops/compressedOops.inline.hpp"
 #include "oops/instanceClassLoaderKlass.hpp"
 #include "oops/instanceMirrorKlass.hpp"
@@ -67,7 +68,7 @@
 #include "runtime/vmThread.hpp"
 #include "runtime/vmOperations.hpp"
 #include "utilities/align.hpp"
-#include "utilities/bitMap.hpp"
+#include "utilities/bitMap.inline.hpp"
 #include "utilities/defaultStream.hpp"
 #include "utilities/hashtable.inline.hpp"
 #if INCLUDE_G1GC
@@ -82,8 +83,8 @@
 bool MetaspaceShared::_remapped_readwrite = false;
 address MetaspaceShared::_i2i_entry_code_buffers = NULL;
 size_t MetaspaceShared::_i2i_entry_code_buffers_size = 0;
-size_t MetaspaceShared::_core_spaces_size = 0;
 void* MetaspaceShared::_shared_metaspace_static_top = NULL;
+intx MetaspaceShared::_relocation_delta;
 
 // The CDS archive is divided into the following regions:
 //     mc  - misc code (the method entry trampolines)
@@ -147,9 +148,21 @@
   return p;
 }
 
+void DumpRegion::append_intptr_t(intptr_t n, bool need_to_mark) {
+  assert(is_aligned(_top, sizeof(intptr_t)), "bad alignment");
+  intptr_t *p = (intptr_t*)_top;
+  char* newtop = _top + sizeof(intptr_t);
+  expand_top_to(newtop);
+  *p = n;
+  if (need_to_mark) {
+    ArchivePtrMarker::mark_pointer(p);
+  }
+}
+
 void DumpRegion::print(size_t total_bytes) const {
   tty->print_cr("%-3s space: " SIZE_FORMAT_W(9) " [ %4.1f%% of total] out of " SIZE_FORMAT_W(9) " bytes [%5.1f%% used] at " INTPTR_FORMAT,
-                _name, used(), percent_of(used(), total_bytes), reserved(), percent_of(used(), reserved()), p2i(_base));
+                _name, used(), percent_of(used(), total_bytes), reserved(), percent_of(used(), reserved()),
+                p2i(_base + MetaspaceShared::final_delta()));
 }
 
 void DumpRegion::print_out_of_space_msg(const char* failing_region, size_t needed_bytes) {
@@ -172,14 +185,14 @@
   }
 }
 
-DumpRegion _mc_region("mc"), _ro_region("ro"), _rw_region("rw"), _md_region("md");
-size_t _total_closed_archive_region_size = 0, _total_open_archive_region_size = 0;
+static DumpRegion _mc_region("mc"), _ro_region("ro"), _rw_region("rw"), _md_region("md");
+static size_t _total_closed_archive_region_size = 0, _total_open_archive_region_size = 0;
 
 void MetaspaceShared::init_shared_dump_space(DumpRegion* first_space, address first_space_bottom) {
   // Start with 0 committed bytes. The memory will be committed as needed by
   // MetaspaceShared::commit_shared_space_to().
   if (!_shared_vs.initialize(_shared_rs, 0)) {
-    vm_exit_during_initialization("Unable to allocate memory for shared space");
+    fatal("Unable to allocate memory for shared space");
   }
   first_space->init(&_shared_rs, (char*)first_space_bottom);
 }
@@ -209,73 +222,32 @@
   return _ro_region.allocate(num_bytes);
 }
 
-void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() {
-  assert(UseSharedSpaces, "Must be called when UseSharedSpaces is enabled");
-
-  // If using shared space, open the file that contains the shared space
-  // and map in the memory before initializing the rest of metaspace (so
-  // the addresses don't conflict)
-  FileMapInfo* mapinfo = new FileMapInfo(true);
-
-  // Open the shared archive file, read and validate the header. If
-  // initialization fails, shared spaces [UseSharedSpaces] are
-  // disabled and the file is closed.
-  // Map in spaces now also
-  if (mapinfo->initialize(true) && map_shared_spaces(mapinfo)) {
-    size_t cds_total = core_spaces_size();
-    address cds_address = (address)mapinfo->region_addr(0);
-    char* cds_end = (char *)align_up(cds_address + cds_total,
-                                     Metaspace::reserve_alignment());
-
-    // Mapping the dynamic archive before allocating the class space
-    cds_end = initialize_dynamic_runtime_shared_spaces((char*)cds_address, cds_end);
-
-#ifdef _LP64
-    if (Metaspace::using_class_space()) {
-      // If UseCompressedClassPointers is set then allocate the metaspace area
-      // above the heap and above the CDS area (if it exists).
-      Metaspace::allocate_metaspace_compressed_klass_ptrs(cds_end, cds_address);
-      // map_heap_regions() compares the current narrow oop and klass encodings
-      // with the archived ones, so it must be done after all encodings are determined.
-      mapinfo->map_heap_regions();
-    }
-    CompressedKlassPointers::set_range(CompressedClassSpaceSize);
-#endif // _LP64
+// When reserving an address range using ReservedSpace, we need an alignment that satisfies both:
+// os::vm_allocation_granularity() -- so that we can sub-divide this range into multiple mmap regions,
+//                                    while keeping the first range at offset 0 of this range.
+// Metaspace::reserve_alignment()  -- so we can pass the region to
+//                                    Metaspace::allocate_metaspace_compressed_klass_ptrs.
+size_t MetaspaceShared::reserved_space_alignment() {
+  size_t os_align = os::vm_allocation_granularity();
+  size_t ms_align = Metaspace::reserve_alignment();
+  if (os_align >= ms_align) {
+    assert(os_align % ms_align == 0, "must be a multiple");
+    return os_align;
   } else {
-    assert(!mapinfo->is_open() && !UseSharedSpaces,
-           "archive file not closed or shared spaces not disabled.");
+    assert(ms_align % os_align == 0, "must be a multiple");
+    return ms_align;
   }
 }
 
-char* MetaspaceShared::initialize_dynamic_runtime_shared_spaces(
-        char* static_start, char* static_end) {
-  assert(UseSharedSpaces, "must be runtime");
-  char* cds_end = static_end;
-  if (!DynamicDumpSharedSpaces) {
-    address dynamic_top = DynamicArchive::map();
-    if (dynamic_top != NULL) {
-      assert(dynamic_top > (address)static_start, "Unexpected layout");
-      MetaspaceObj::expand_shared_metaspace_range(dynamic_top);
-      cds_end = (char *)align_up(dynamic_top, Metaspace::reserve_alignment());
-    }
-  }
-  return cds_end;
-}
-
-ReservedSpace* MetaspaceShared::reserve_shared_rs(size_t size, size_t alignment,
-                                                  bool large, char* requested_address) {
-  if (requested_address != NULL) {
-    _shared_rs = ReservedSpace(size, alignment, large, requested_address);
-  } else {
-    _shared_rs = ReservedSpace(size, alignment, large);
-  }
-  return &_shared_rs;
+ReservedSpace MetaspaceShared::reserve_shared_space(size_t size, char* requested_address) {
+  bool large_pages = false; // Don't use large pages for the CDS archive.
+  assert(is_aligned(requested_address, reserved_space_alignment()), "must be");
+  return ReservedSpace(size, reserved_space_alignment(), large_pages, requested_address);
 }
 
 void MetaspaceShared::initialize_dumptime_shared_and_meta_spaces() {
   assert(DumpSharedSpaces, "should be called for dump time only");
-  const size_t reserve_alignment = Metaspace::reserve_alignment();
-  bool large_pages = false; // No large pages when dumping the CDS archive.
+  const size_t reserve_alignment = reserved_space_alignment();
   char* shared_base = (char*)align_up((char*)SharedBaseAddress, reserve_alignment);
 
 #ifdef _LP64
@@ -296,15 +268,22 @@
   size_t cds_total = align_down(256*M, reserve_alignment);
 #endif
 
+  bool use_requested_base = true;
+  if (ArchiveRelocationMode == 1) {
+    log_info(cds)("ArchiveRelocationMode == 1: always allocate class space at an alternative address");
+    use_requested_base = false;
+  }
+
   // First try to reserve the space at the specified SharedBaseAddress.
-  //_shared_rs = ReservedSpace(cds_total, reserve_alignment, large_pages, shared_base);
-  reserve_shared_rs(cds_total, reserve_alignment, large_pages, shared_base);
+  assert(!_shared_rs.is_reserved(), "must be");
+  if (use_requested_base) {
+    _shared_rs = reserve_shared_space(cds_total, shared_base);
+  }
   if (_shared_rs.is_reserved()) {
     assert(shared_base == 0 || _shared_rs.base() == shared_base, "should match");
   } else {
     // Get a mmap region anywhere if the SharedBaseAddress fails.
-    //_shared_rs = ReservedSpace(cds_total, reserve_alignment, large_pages);
-    reserve_shared_rs(cds_total, reserve_alignment, large_pages, NULL);
+    _shared_rs = reserve_shared_space(cds_total);
   }
   if (!_shared_rs.is_reserved()) {
     vm_exit_during_initialization("Unable to reserve memory for shared space",
@@ -442,6 +421,8 @@
   assert(commit <= uncommitted, "sanity");
 
   bool result = _shared_vs.expand_by(commit, false);
+  ArchivePtrMarker::expand_ptr_end((address*)_shared_vs.high());
+
   if (!result) {
     vm_exit_during_initialization(err_msg("Failed to expand shared space to " SIZE_FORMAT " bytes",
                                           need_committed_size));
@@ -451,6 +432,10 @@
                 commit, _shared_vs.actual_committed_size(), _shared_vs.high());
 }
 
+void MetaspaceShared::initialize_ptr_marker(CHeapBitMap* ptrmap) {
+  ArchivePtrMarker::initialize(ptrmap, (address*)_shared_vs.low(), (address*)_shared_vs.high());
+}
+
 // Read/write a data stream for restoring/preserving metadata pointers and
 // miscellaneous data from/to the shared archive file.
 
@@ -469,6 +454,7 @@
   soc->do_tag(sizeof(Symbol));
 
   // Dump/restore miscellaneous metadata.
+  JavaClasses::serialize_offsets(soc);
   Universe::serialize(soc);
   soc->do_tag(--tag);
 
@@ -482,7 +468,6 @@
   HeapShared::serialize_subgraph_info_table_header(soc);
   SystemDictionaryShared::serialize_dictionary_headers(soc);
 
-  JavaClasses::serialize_offsets(soc);
   InstanceMirrorKlass::serialize_offsets(soc);
   soc->do_tag(--tag);
 
@@ -705,7 +690,9 @@
   // Switch the vtable pointer to point to the cloned vtable.
   static void patch(Metadata* obj) {
     assert(DumpSharedSpaces, "dump-time only");
+    assert(MetaspaceShared::is_in_output_space(obj), "must be");
     *(void**)obj = (void*)(_info->cloned_vtable());
+    ArchivePtrMarker::mark_pointer(obj);
   }
 
   static bool is_valid_shared_object(const T* obj) {
@@ -799,7 +786,8 @@
 }
 
 #define ALLOC_CPP_VTABLE_CLONE(c) \
-  _cloned_cpp_vtptrs[c##_Kind] = CppVtableCloner<c>::allocate(#c);
+  _cloned_cpp_vtptrs[c##_Kind] = CppVtableCloner<c>::allocate(#c); \
+  ArchivePtrMarker::mark_pointer(&_cloned_cpp_vtptrs[c##_Kind]);
 
 #define CLONE_CPP_VTABLE(c) \
   p = CppVtableCloner<c>::clone_vtable(#c, (CppVtableInfo*)p);
@@ -965,7 +953,7 @@
   assert(size % sizeof(intptr_t) == 0, "bad size");
   do_tag((int)size);
   while (size > 0) {
-    _dump_region->append_intptr_t(*(intptr_t*)start);
+    _dump_region->append_intptr_t(*(intptr_t*)start, true);
     start += sizeof(intptr_t);
     size -= sizeof(intptr_t);
   }
@@ -1129,9 +1117,13 @@
                                  GrowableArray<ArchiveHeapOopmapInfo>* oopmaps);
   void dump_symbols();
   char* dump_read_only_tables();
+  void print_class_stats();
   void print_region_stats();
+  void print_bitmap_region_stats(size_t size, size_t total_size);
   void print_heap_region_stats(GrowableArray<MemRegion> *heap_mem,
-                               const char *name, const size_t total_size);
+                               const char *name, size_t total_size);
+  void relocate_to_default_base_address(CHeapBitMap* ptrmap);
+
 public:
 
   VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; }
@@ -1276,6 +1268,15 @@
       ref->metaspace_pointers_do_at(&refer, new_loc);
       return true; // recurse into ref.obj()
     }
+    virtual void push_special(SpecialRef type, Ref* ref, intptr_t* p) {
+      assert(type == _method_entry_ref, "only special type allowed for now");
+      address obj = ref->obj();
+      address new_obj = get_new_loc(ref);
+      size_t offset = pointer_delta(p, obj,  sizeof(u1));
+      intptr_t* new_p = (intptr_t*)(new_obj + offset);
+      assert(*p == *new_p, "must be a copy");
+      ArchivePtrMarker::mark_pointer((address*)new_p);
+    }
   };
 
   // Relocate a reference to point to its shallow copy
@@ -1284,6 +1285,7 @@
     virtual bool do_ref(Ref* ref, bool read_only) {
       if (ref->not_null()) {
         ref->update(get_new_loc(ref));
+        ArchivePtrMarker::mark_pointer(ref->addr());
       }
       return false; // Do not recurse.
     }
@@ -1440,7 +1442,71 @@
   return start;
 }
 
+void VM_PopulateDumpSharedSpace::print_class_stats() {
+  tty->print_cr("Number of classes %d", _global_klass_objects->length());
+  {
+    int num_type_array = 0, num_obj_array = 0, num_inst = 0;
+    for (int i = 0; i < _global_klass_objects->length(); i++) {
+      Klass* k = _global_klass_objects->at(i);
+      if (k->is_instance_klass()) {
+        num_inst ++;
+      } else if (k->is_objArray_klass()) {
+        num_obj_array ++;
+      } else {
+        assert(k->is_typeArray_klass(), "sanity");
+        num_type_array ++;
+      }
+    }
+    tty->print_cr("    instance classes   = %5d", num_inst);
+    tty->print_cr("    obj array classes  = %5d", num_obj_array);
+    tty->print_cr("    type array classes = %5d", num_type_array);
+  }
+}
+
+void VM_PopulateDumpSharedSpace::relocate_to_default_base_address(CHeapBitMap* ptrmap) {
+  intx addr_delta = MetaspaceShared::final_delta();
+  if (addr_delta == 0) {
+    ArchivePtrMarker::compact((address)SharedBaseAddress, (address)_md_region.top());
+  } else {
+    // We are not able to reserve space at Arguments::default_SharedBaseAddress() (due to ASLR).
+    // This means that the current content of the archive is based on a random
+    // address. Let's relocate all the pointers, so that it can be mapped to
+    // Arguments::default_SharedBaseAddress() without runtime relocation.
+    //
+    // Note: both the base and dynamic archive are written with
+    // FileMapHeader::_shared_base_address == Arguments::default_SharedBaseAddress()
+
+    // Patch all pointers that are marked by ptrmap within this region,
+    // where we have just dumped all the metaspace data.
+    address patch_base = (address)SharedBaseAddress;
+    address patch_end  = (address)_md_region.top();
+    size_t size = patch_end - patch_base;
+
+    // the current value of the pointers to be patched must be within this
+    // range (i.e., must point to valid metaspace objects)
+    address valid_old_base = patch_base;
+    address valid_old_end  = patch_end;
+
+    // after patching, the pointers must point inside this range
+    // (the requested location of the archive, as mapped at runtime).
+    address valid_new_base = (address)Arguments::default_SharedBaseAddress();
+    address valid_new_end  = valid_new_base + size;
+
+    log_debug(cds)("Relocating archive from [" INTPTR_FORMAT " - " INTPTR_FORMAT " ] to "
+                   "[" INTPTR_FORMAT " - " INTPTR_FORMAT " ]", p2i(patch_base), p2i(patch_end),
+                   p2i(valid_new_base), p2i(valid_new_end));
+
+    SharedDataRelocator<true> patcher((address*)patch_base, (address*)patch_end, valid_old_base, valid_old_end,
+                                      valid_new_base, valid_new_end, addr_delta, ptrmap);
+    ptrmap->iterate(&patcher);
+    ArchivePtrMarker::compact(patcher.max_non_null_offset());
+  }
+}
+
 void VM_PopulateDumpSharedSpace::doit() {
+  CHeapBitMap ptrmap;
+  MetaspaceShared::initialize_ptr_marker(&ptrmap);
+
   // We should no longer allocate anything from the metaspace, so that:
   //
   // (1) Metaspace::allocate might trigger GC if we have run out of
@@ -1472,24 +1538,7 @@
   CollectClassesClosure collect_classes;
   ClassLoaderDataGraph::loaded_classes_do(&collect_classes);
 
-  tty->print_cr("Number of classes %d", _global_klass_objects->length());
-  {
-    int num_type_array = 0, num_obj_array = 0, num_inst = 0;
-    for (int i = 0; i < _global_klass_objects->length(); i++) {
-      Klass* k = _global_klass_objects->at(i);
-      if (k->is_instance_klass()) {
-        num_inst ++;
-      } else if (k->is_objArray_klass()) {
-        num_obj_array ++;
-      } else {
-        assert(k->is_typeArray_klass(), "sanity");
-        num_type_array ++;
-      }
-    }
-    tty->print_cr("    instance classes   = %5d", num_inst);
-    tty->print_cr("    obj array classes  = %5d", num_obj_array);
-    tty->print_cr("    type array classes = %5d", num_type_array);
-  }
+  print_class_stats();
 
   // Ensure the ConstMethods won't be modified at run-time
   tty->print("Updating ConstMethods ... ");
@@ -1520,12 +1569,6 @@
   MetaspaceShared::allocate_cpp_vtable_clones();
   _md_region.pack();
 
-  // The 4 core spaces are allocated consecutively mc->rw->ro->md, so there total size
-  // is just the spaces between the two ends.
-  size_t core_spaces_size = _md_region.end() - _mc_region.base();
-  assert(core_spaces_size == (size_t)align_up(core_spaces_size, Metaspace::reserve_alignment()),
-         "should already be aligned");
-
   // During patching, some virtual methods may be called, so at this point
   // the vtables must contain valid methods (as filled in by CppVtableCloner::allocate).
   MetaspaceShared::patch_cpp_vtable_pointers();
@@ -1534,6 +1577,10 @@
   // We don't want to write these addresses into the archive.
   MetaspaceShared::zero_cpp_vtable_clones_for_writing();
 
+  // relocate the data so that it can be mapped to Arguments::default_SharedBaseAddress()
+  // without runtime relocation.
+  relocate_to_default_base_address(&ptrmap);
+
   // Create and write the archive file that maps the shared spaces.
 
   FileMapInfo* mapinfo = new FileMapInfo(true);
@@ -1542,7 +1589,6 @@
   mapinfo->set_misc_data_patching_start(vtbl_list);
   mapinfo->set_i2i_entry_code_buffers(MetaspaceShared::i2i_entry_code_buffers(),
                                       MetaspaceShared::i2i_entry_code_buffers_size());
-  mapinfo->set_core_spaces_size(core_spaces_size);
   mapinfo->open_for_write();
 
   // NOTE: md contains the trampoline code for method entries, which are patched at run time,
@@ -1552,6 +1598,8 @@
   write_region(mapinfo, MetaspaceShared::ro, &_ro_region, /*read_only=*/true, /*allow_exec=*/false);
   write_region(mapinfo, MetaspaceShared::md, &_md_region, /*read_only=*/false,/*allow_exec=*/false);
 
+  mapinfo->write_bitmap_region(ArchivePtrMarker::ptrmap());
+
   _total_closed_archive_region_size = mapinfo->write_archive_heap_regions(
                                         _closed_archive_heap_regions,
                                         _closed_archive_heap_oopmaps,
@@ -1563,6 +1611,7 @@
                                         MetaspaceShared::first_open_archive_heap_region,
                                         MetaspaceShared::max_open_archive_heap_region);
 
+  mapinfo->set_final_requested_base((char*)Arguments::default_SharedBaseAddress());
   mapinfo->set_header_crc(mapinfo->compute_header_crc());
   mapinfo->write_header();
   mapinfo->close();
@@ -1594,12 +1643,16 @@
 
 void VM_PopulateDumpSharedSpace::print_region_stats() {
   // Print statistics of all the regions
+  const size_t bitmap_used = ArchivePtrMarker::ptrmap()->size_in_bytes();
+  const size_t bitmap_reserved = align_up(bitmap_used, Metaspace::reserve_alignment());
   const size_t total_reserved = _ro_region.reserved()  + _rw_region.reserved() +
                                 _mc_region.reserved()  + _md_region.reserved() +
+                                bitmap_reserved +
                                 _total_closed_archive_region_size +
                                 _total_open_archive_region_size;
   const size_t total_bytes = _ro_region.used()  + _rw_region.used() +
                              _mc_region.used()  + _md_region.used() +
+                             bitmap_used +
                              _total_closed_archive_region_size +
                              _total_open_archive_region_size;
   const double total_u_perc = percent_of(total_bytes, total_reserved);
@@ -1608,6 +1661,7 @@
   _rw_region.print(total_reserved);
   _ro_region.print(total_reserved);
   _md_region.print(total_reserved);
+  print_bitmap_region_stats(bitmap_reserved, total_reserved);
   print_heap_region_stats(_closed_archive_heap_regions, "ca", total_reserved);
   print_heap_region_stats(_open_archive_heap_regions, "oa", total_reserved);
 
@@ -1615,8 +1669,13 @@
                  total_bytes, total_reserved, total_u_perc);
 }
 
+void VM_PopulateDumpSharedSpace::print_bitmap_region_stats(size_t size, size_t total_size) {
+  tty->print_cr("bm  space: " SIZE_FORMAT_W(9) " [ %4.1f%% of total] out of " SIZE_FORMAT_W(9) " bytes [100.0%% used] at " INTPTR_FORMAT,
+                size, size/double(total_size)*100.0, size, p2i(NULL));
+}
+
 void VM_PopulateDumpSharedSpace::print_heap_region_stats(GrowableArray<MemRegion> *heap_mem,
-                                                         const char *name, const size_t total_size) {
+                                                         const char *name, size_t total_size) {
   int arr_len = heap_mem == NULL ? 0 : heap_mem->length();
   for (int i = 0; i < arr_len; i++) {
       char* start = (char*)heap_mem->at(i).start();
@@ -1636,9 +1695,13 @@
   o->set_klass(k);
 }
 
-Klass* MetaspaceShared::get_relocated_klass(Klass *k) {
+Klass* MetaspaceShared::get_relocated_klass(Klass *k, bool is_final) {
   assert(DumpSharedSpaces, "sanity");
-  return ArchiveCompactor::get_relocated_klass(k);
+  k = ArchiveCompactor::get_relocated_klass(k);
+  if (is_final) {
+    k = (Klass*)(address(k) + final_delta());
+  }
+  return k;
 }
 
 class LinkSharedClassesClosure : public KlassClosure {
@@ -1947,8 +2010,9 @@
   }
 }
 
-void MetaspaceShared::set_shared_metaspace_range(void* base, void* top) {
-  _shared_metaspace_static_top = top;
+void MetaspaceShared::set_shared_metaspace_range(void* base, void *static_top, void* top) {
+  assert(base <= static_top && static_top <= top, "must be");
+  _shared_metaspace_static_top = static_top;
   MetaspaceObj::set_shared_metaspace_range(base, top);
 }
 
@@ -1973,49 +2037,312 @@
   }
 }
 
-// Map shared spaces at requested addresses and return if succeeded.
-bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) {
-  size_t image_alignment = mapinfo->alignment();
+void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() {
+  assert(UseSharedSpaces, "Must be called when UseSharedSpaces is enabled");
+  MapArchiveResult result = MAP_ARCHIVE_OTHER_FAILURE;
+  FileMapInfo* static_mapinfo = open_static_archive();
+  FileMapInfo* dynamic_mapinfo = NULL;
+
+  if (static_mapinfo != NULL) {
+    dynamic_mapinfo = open_dynamic_archive();
+
+    // First try to map at the requested address
+    result = map_archives(static_mapinfo, dynamic_mapinfo, true);
+    if (result == MAP_ARCHIVE_MMAP_FAILURE) {
+      // Mapping has failed (probably due to ASLR). Let's map at an address chosen
+      // by the OS.
+      result = map_archives(static_mapinfo, dynamic_mapinfo, false);
+    }
+  }
+
+  if (result == MAP_ARCHIVE_SUCCESS) {
+    bool dynamic_mapped = (dynamic_mapinfo != NULL && dynamic_mapinfo->is_mapped());
+    char* cds_base = static_mapinfo->mapped_base();
+    char* cds_end =  dynamic_mapped ? dynamic_mapinfo->mapped_end() : static_mapinfo->mapped_end();
+    set_shared_metaspace_range(cds_base, static_mapinfo->mapped_end(), cds_end);
+    _relocation_delta = static_mapinfo->relocation_delta();
+    if (dynamic_mapped) {
+      FileMapInfo::set_shared_path_table(dynamic_mapinfo);
+    } else {
+      FileMapInfo::set_shared_path_table(static_mapinfo);
+    }
+  } else {
+    set_shared_metaspace_range(NULL, NULL, NULL);
+    UseSharedSpaces = false;
+    FileMapInfo::fail_continue("Unable to map shared spaces");
+    if (PrintSharedArchiveAndExit) {
+      vm_exit_during_initialization("Unable to use shared archive.");
+    }
+  }
+
+  if (static_mapinfo != NULL && !static_mapinfo->is_mapped()) {
+    delete static_mapinfo;
+  }
+  if (dynamic_mapinfo != NULL && !dynamic_mapinfo->is_mapped()) {
+    delete dynamic_mapinfo;
+  }
+}
+
+FileMapInfo* MetaspaceShared::open_static_archive() {
+  FileMapInfo* mapinfo = new FileMapInfo(true);
+  if (!mapinfo->initialize()) {
+    delete(mapinfo);
+    return NULL;
+  }
+  return mapinfo;
+}
+
+FileMapInfo* MetaspaceShared::open_dynamic_archive() {
+  if (DynamicDumpSharedSpaces) {
+    return NULL;
+  }
+  if (Arguments::GetSharedDynamicArchivePath() == NULL) {
+    return NULL;
+  }
 
-#ifndef _WINDOWS
-  // Map in the shared memory and then map the regions on top of it.
-  // On Windows, don't map the memory here because it will cause the
-  // mappings of the regions to fail.
-  ReservedSpace shared_rs = mapinfo->reserve_shared_memory();
-  if (!shared_rs.is_reserved()) return false;
-#endif
+  FileMapInfo* mapinfo = new FileMapInfo(false);
+  if (!mapinfo->initialize()) {
+    delete(mapinfo);
+    return NULL;
+  }
+  return mapinfo;
+}
+
+// use_requested_addr:
+//  true  = map at FileMapHeader::_requested_base_address
+//  false = map at an alternative address picked by OS.
+MapArchiveResult MetaspaceShared::map_archives(FileMapInfo* static_mapinfo, FileMapInfo* dynamic_mapinfo,
+                                               bool use_requested_addr) {
+  PRODUCT_ONLY(if (ArchiveRelocationMode == 1 && use_requested_addr) {
+      // For product build only -- this is for benchmarking the cost of doing relocation.
+      // For debug builds, the check is done in FileMapInfo::map_regions for better test coverage.
+      log_info(cds)("ArchiveRelocationMode == 1: always map archive(s) at an alternative address");
+      return MAP_ARCHIVE_MMAP_FAILURE;
+    });
+
+  if (ArchiveRelocationMode == 2 && !use_requested_addr) {
+    log_info(cds)("ArchiveRelocationMode == 2: never map archive(s) at an alternative address");
+    return MAP_ARCHIVE_MMAP_FAILURE;
+  };
+
+  if (dynamic_mapinfo != NULL) {
+    // Ensure that the OS won't be able to allocate new memory spaces between the two
+    // archives, or else it would mess up the simple comparision in MetaspaceObj::is_shared().
+    assert(static_mapinfo->mapping_end_offset() == dynamic_mapinfo->mapping_base_offset(), "no gap");
+  }
 
-  assert(!DumpSharedSpaces, "Should not be called with DumpSharedSpaces");
+  ReservedSpace main_rs, archive_space_rs, class_space_rs;
+  MapArchiveResult result = MAP_ARCHIVE_OTHER_FAILURE;
+  char* mapped_base_address = reserve_address_space_for_archives(static_mapinfo, dynamic_mapinfo,
+                                                                 use_requested_addr, main_rs, archive_space_rs,
+                                                                 class_space_rs);
+  if (mapped_base_address == NULL) {
+    result = MAP_ARCHIVE_MMAP_FAILURE;
+  } else {
+    log_debug(cds)("Reserved archive_space_rs     [" INTPTR_FORMAT " - " INTPTR_FORMAT "] (" SIZE_FORMAT ") bytes",
+                   p2i(archive_space_rs.base()), p2i(archive_space_rs.end()), archive_space_rs.size());
+    log_debug(cds)("Reserved class_space_rs [" INTPTR_FORMAT " - " INTPTR_FORMAT "] (" SIZE_FORMAT ") bytes",
+                   p2i(class_space_rs.base()), p2i(class_space_rs.end()), class_space_rs.size());
+    MapArchiveResult static_result = map_archive(static_mapinfo, mapped_base_address, archive_space_rs);
+    MapArchiveResult dynamic_result = (static_result == MAP_ARCHIVE_SUCCESS) ?
+                                     map_archive(dynamic_mapinfo, mapped_base_address, archive_space_rs) : MAP_ARCHIVE_OTHER_FAILURE;
 
-  // Map each shared region
-  int regions[] = {mc, rw, ro, md};
-  size_t len = sizeof(regions)/sizeof(int);
-  char* saved_base[] = {NULL, NULL, NULL, NULL};
-  char* top = mapinfo->map_regions(regions, saved_base, len );
+    if (static_result == MAP_ARCHIVE_SUCCESS) {
+      if (dynamic_result == MAP_ARCHIVE_SUCCESS) {
+        result = MAP_ARCHIVE_SUCCESS;
+      } else if (dynamic_result == MAP_ARCHIVE_OTHER_FAILURE) {
+        assert(dynamic_mapinfo != NULL && !dynamic_mapinfo->is_mapped(), "must have failed");
+        // No need to retry mapping the dynamic archive again, as it will never succeed
+        // (bad file, etc) -- just keep the base archive.
+        log_warning(cds, dynamic)("Unable to use shared archive. The top archive failed to load: %s",
+                                  dynamic_mapinfo->full_path());
+        result = MAP_ARCHIVE_SUCCESS;
+        // TODO, we can give the unused space for the dynamic archive to class_space_rs, but there's no
+        // easy API to do that right now.
+      } else {
+        result = MAP_ARCHIVE_MMAP_FAILURE;
+      }
+    } else if (static_result == MAP_ARCHIVE_OTHER_FAILURE) {
+      result = MAP_ARCHIVE_OTHER_FAILURE;
+    } else {
+      result = MAP_ARCHIVE_MMAP_FAILURE;
+    }
+  }
 
-  if (top != NULL &&
-      (image_alignment == (size_t)os::vm_allocation_granularity()) &&
-      mapinfo->validate_shared_path_table()) {
-    // Success -- set up MetaspaceObj::_shared_metaspace_{base,top} for
-    // fast checking in MetaspaceShared::is_in_shared_metaspace() and
-    // MetaspaceObj::is_shared().
-    _core_spaces_size = mapinfo->core_spaces_size();
-    set_shared_metaspace_range((void*)saved_base[0], (void*)top);
-    return true;
+  if (result == MAP_ARCHIVE_SUCCESS) {
+    if (!main_rs.is_reserved() && class_space_rs.is_reserved()) {
+      MemTracker::record_virtual_memory_type((address)class_space_rs.base(), mtClass);
+    }
+    SharedBaseAddress = (size_t)mapped_base_address;
+    LP64_ONLY({
+        if (Metaspace::using_class_space()) {
+          assert(class_space_rs.is_reserved(), "must be");
+          char* cds_base = static_mapinfo->mapped_base();
+          Metaspace::allocate_metaspace_compressed_klass_ptrs(class_space_rs, NULL, (address)cds_base);
+          // map_heap_regions() compares the current narrow oop and klass encodings
+          // with the archived ones, so it must be done after all encodings are determined.
+          static_mapinfo->map_heap_regions();
+        }
+        CompressedKlassPointers::set_range(CompressedClassSpaceSize);
+      });
+  } else {
+    unmap_archive(static_mapinfo);
+    unmap_archive(dynamic_mapinfo);
+    release_reserved_spaces(main_rs, archive_space_rs, class_space_rs);
+  }
+
+  return result;
+}
+
+char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_mapinfo,
+                                                          FileMapInfo* dynamic_mapinfo,
+                                                          bool use_requested_addr,
+                                                          ReservedSpace& main_rs,
+                                                          ReservedSpace& archive_space_rs,
+                                                          ReservedSpace& class_space_rs) {
+  const bool use_klass_space = NOT_LP64(false) LP64_ONLY(Metaspace::using_class_space());
+  const size_t class_space_size = NOT_LP64(0) LP64_ONLY(Metaspace::compressed_class_space_size());
+
+  if (use_klass_space) {
+    assert(class_space_size > 0, "CompressedClassSpaceSize must have been validated");
+  }
+  if (use_requested_addr && !is_aligned(static_mapinfo->requested_base_address(), reserved_space_alignment())) {
+    return NULL;
+  }
+
+  // Size and requested location of the archive_space_rs (for both static and dynamic archives)
+  size_t base_offset = static_mapinfo->mapping_base_offset();
+  size_t end_offset  = (dynamic_mapinfo == NULL) ? static_mapinfo->mapping_end_offset() : dynamic_mapinfo->mapping_end_offset();
+  assert(base_offset == 0, "must be");
+  assert(is_aligned(end_offset,  os::vm_allocation_granularity()), "must be");
+  assert(is_aligned(base_offset, os::vm_allocation_granularity()), "must be");
+
+  // In case reserved_space_alignment() != os::vm_allocation_granularity()
+  assert((size_t)os::vm_allocation_granularity() <= reserved_space_alignment(), "must be");
+  end_offset = align_up(end_offset, reserved_space_alignment());
+
+  size_t archive_space_size = end_offset - base_offset;
+
+  // Special handling for Windows because it cannot mmap into a reserved space:
+  //    use_requested_addr: We just map each region individually, and give up if any one of them fails.
+  //   !use_requested_addr: We reserve the space first, and then os::read in all the regions (instead of mmap).
+  //                        We're going to patch all the pointers anyway so there's no benefit for mmap.
+
+  if (use_requested_addr) {
+    char* archive_space_base = static_mapinfo->requested_base_address() + base_offset;
+    char* archive_space_end  = archive_space_base + archive_space_size;
+    if (!MetaspaceShared::use_windows_memory_mapping()) {
+      archive_space_rs = reserve_shared_space(archive_space_size, archive_space_base);
+      if (!archive_space_rs.is_reserved()) {
+        return NULL;
+      }
+    }
+    if (use_klass_space) {
+      // Make sure we can map the klass space immediately following the archive_space space
+      char* class_space_base = archive_space_end;
+      class_space_rs = reserve_shared_space(class_space_size, class_space_base);
+      if (!class_space_rs.is_reserved()) {
+        return NULL;
+      }
+    }
+    return static_mapinfo->requested_base_address();
   } else {
-    mapinfo->unmap_regions(regions, saved_base, len);
-#ifndef _WINDOWS
-    // Release the entire mapped region
-    shared_rs.release();
-#endif
-    // If -Xshare:on is specified, print out the error message and exit VM,
-    // otherwise, set UseSharedSpaces to false and continue.
-    if (RequireSharedSpaces || PrintSharedArchiveAndExit) {
-      vm_exit_during_initialization("Unable to use shared archive.", "Failed map_region for using -Xshare:on.");
+    if (use_klass_space) {
+      main_rs = reserve_shared_space(archive_space_size + class_space_size);
+      if (main_rs.is_reserved()) {
+        archive_space_rs = main_rs.first_part(archive_space_size, reserved_space_alignment(), /*split=*/true);
+        class_space_rs = main_rs.last_part(archive_space_size);
+      }
+    } else {
+      main_rs = reserve_shared_space(archive_space_size);
+      archive_space_rs = main_rs;
+    }
+    if (archive_space_rs.is_reserved()) {
+      return archive_space_rs.base();
     } else {
-      FLAG_SET_DEFAULT(UseSharedSpaces, false);
+      return NULL;
+    }
+  }
+}
+
+void MetaspaceShared::release_reserved_spaces(ReservedSpace& main_rs,
+                                              ReservedSpace& archive_space_rs,
+                                              ReservedSpace& class_space_rs) {
+  if (main_rs.is_reserved()) {
+    assert(main_rs.contains(archive_space_rs.base()), "must be");
+    assert(main_rs.contains(class_space_rs.base()), "must be");
+    log_debug(cds)("Released shared space (archive+classes) " INTPTR_FORMAT, p2i(main_rs.base()));
+    main_rs.release();
+  } else {
+    if (archive_space_rs.is_reserved()) {
+      log_debug(cds)("Released shared space (archive) " INTPTR_FORMAT, p2i(archive_space_rs.base()));
+      archive_space_rs.release();
+    }
+    if (class_space_rs.is_reserved()) {
+      log_debug(cds)("Released shared space (classes) " INTPTR_FORMAT, p2i(class_space_rs.base()));
+      class_space_rs.release();
     }
-    return false;
+  }
+}
+
+static int static_regions[]  = {MetaspaceShared::mc,
+                                MetaspaceShared::rw,
+                                MetaspaceShared::ro,
+                                MetaspaceShared::md};
+static int dynamic_regions[] = {MetaspaceShared::rw,
+                                MetaspaceShared::ro,
+                                MetaspaceShared::mc};
+static int static_regions_count  = 4;
+static int dynamic_regions_count = 3;
+
+MapArchiveResult MetaspaceShared::map_archive(FileMapInfo* mapinfo, char* mapped_base_address, ReservedSpace rs) {
+  assert(UseSharedSpaces, "must be runtime");
+  if (mapinfo == NULL) {
+    return MAP_ARCHIVE_SUCCESS; // no error has happeed -- trivially succeeded.
+  }
+
+  mapinfo->set_is_mapped(false);
+
+  if (mapinfo->alignment() != (size_t)os::vm_allocation_granularity()) {
+    log_error(cds)("Unable to map CDS archive -- os::vm_allocation_granularity() expected: " SIZE_FORMAT
+                   " actual: %d", mapinfo->alignment(), os::vm_allocation_granularity());
+    return MAP_ARCHIVE_OTHER_FAILURE;
+  }
+
+  MapArchiveResult result = mapinfo->is_static() ?
+    mapinfo->map_regions(static_regions, static_regions_count, mapped_base_address, rs) :
+    mapinfo->map_regions(dynamic_regions, dynamic_regions_count, mapped_base_address, rs);
+
+  if (result != MAP_ARCHIVE_SUCCESS) {
+    unmap_archive(mapinfo);
+    return result;
+  }
+
+  if (mapinfo->is_static()) {
+    if (!mapinfo->validate_shared_path_table()) {
+      unmap_archive(mapinfo);
+      return MAP_ARCHIVE_OTHER_FAILURE;
+    }
+  } else {
+    if (!DynamicArchive::validate(mapinfo)) {
+      unmap_archive(mapinfo);
+      return MAP_ARCHIVE_OTHER_FAILURE;
+    }
+  }
+
+  mapinfo->set_is_mapped(true);
+  return MAP_ARCHIVE_SUCCESS;
+}
+
+void MetaspaceShared::unmap_archive(FileMapInfo* mapinfo) {
+  assert(UseSharedSpaces, "must be runtime");
+  if (mapinfo != NULL) {
+    if (mapinfo->is_static()) {
+      mapinfo->unmap_regions(static_regions, static_regions_count);
+    } else {
+      mapinfo->unmap_regions(dynamic_regions, dynamic_regions_count);
+    }
+    mapinfo->set_is_mapped(false);
   }
 }
 
@@ -2023,17 +2350,15 @@
 // serialize it out to its various destinations.
 
 void MetaspaceShared::initialize_shared_spaces() {
-  FileMapInfo *mapinfo = FileMapInfo::current_info();
-  _i2i_entry_code_buffers = mapinfo->i2i_entry_code_buffers();
-  _i2i_entry_code_buffers_size = mapinfo->i2i_entry_code_buffers_size();
-  // _core_spaces_size is loaded from the shared archive immediatelly after mapping
-  assert(_core_spaces_size == mapinfo->core_spaces_size(), "sanity");
-  char* buffer = mapinfo->misc_data_patching_start();
+  FileMapInfo *static_mapinfo = FileMapInfo::current_info();
+  _i2i_entry_code_buffers = static_mapinfo->i2i_entry_code_buffers();
+  _i2i_entry_code_buffers_size = static_mapinfo->i2i_entry_code_buffers_size();
+  char* buffer = static_mapinfo->misc_data_patching_start();
   clone_cpp_vtables((intptr_t*)buffer);
 
   // Verify various attributes of the archive, plus initialize the
   // shared string/symbol tables
-  buffer = mapinfo->serialized_data_start();
+  buffer = static_mapinfo->serialized_data_start();
   intptr_t* array = (intptr_t*)buffer;
   ReadClosure rc(&array);
   serialize(&rc);
@@ -2041,17 +2366,26 @@
   // Initialize the run-time symbol table.
   SymbolTable::create_table();
 
-  mapinfo->patch_archived_heap_embedded_pointers();
+  static_mapinfo->patch_archived_heap_embedded_pointers();
 
   // Close the mapinfo file
-  mapinfo->close();
+  static_mapinfo->close();
+
+  FileMapInfo *dynamic_mapinfo = FileMapInfo::dynamic_info();
+  if (dynamic_mapinfo != NULL) {
+    intptr_t* buffer = (intptr_t*)dynamic_mapinfo->serialized_data_start();
+    ReadClosure rc(&buffer);
+    SymbolTable::serialize_shared_table_header(&rc, false);
+    SystemDictionaryShared::serialize_dictionary_headers(&rc, false);
+    dynamic_mapinfo->close();
+  }
 
   if (PrintSharedArchiveAndExit) {
     if (PrintSharedDictionary) {
       tty->print_cr("\nShared classes:\n");
       SystemDictionaryShared::print_on(tty);
     }
-    if (_archive_loading_failed) {
+    if (FileMapInfo::current_info() == NULL || _archive_loading_failed) {
       tty->print_cr("archive is invalid");
       vm_exit(1);
     } else {
@@ -2094,3 +2428,10 @@
   vm_exit_during_initialization(err_msg("Unable to allocate from '%s' region", name),
                                 "Please reduce the number of shared classes.");
 }
+
+// This is used to relocate the pointers so that the archive can be mapped at
+// Arguments::default_SharedBaseAddress() without runtime relocation.
+intx MetaspaceShared::final_delta() {
+  return intx(Arguments::default_SharedBaseAddress())  // We want the archive to be mapped to here at runtime
+       - intx(SharedBaseAddress);                      // .. but the archive is mapped at here at dump time
+}
--- a/src/hotspot/share/memory/metaspaceShared.hpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/memory/metaspaceShared.hpp	Wed Nov 13 16:36:54 2019 -0800
@@ -37,6 +37,13 @@
 #define MAX_SHARED_DELTA                (0x7FFFFFFF)
 
 class FileMapInfo;
+class CHeapBitMap;
+
+enum MapArchiveResult {
+  MAP_ARCHIVE_SUCCESS,
+  MAP_ARCHIVE_MMAP_FAILURE,
+  MAP_ARCHIVE_OTHER_FAILURE
+};
 
 class MetaspaceSharedStats {
 public:
@@ -62,13 +69,7 @@
   char* expand_top_to(char* newtop);
   char* allocate(size_t num_bytes, size_t alignment=BytesPerWord);
 
-  void append_intptr_t(intptr_t n) {
-    assert(is_aligned(_top, sizeof(intptr_t)), "bad alignment");
-    intptr_t *p = (intptr_t*)_top;
-    char* newtop = _top + sizeof(intptr_t);
-    expand_top_to(newtop);
-    *p = n;
-  }
+  void append_intptr_t(intptr_t n, bool need_to_mark = false);
 
   char* base()      const { return _base;        }
   char* top()       const { return _top;         }
@@ -117,17 +118,15 @@
   }
 
   void do_ptr(void** p) {
-    _dump_region->append_intptr_t((intptr_t)*p);
+    _dump_region->append_intptr_t((intptr_t)*p, true);
   }
 
   void do_u4(u4* p) {
-    void* ptr = (void*)(uintx(*p));
-    do_ptr(&ptr);
+    _dump_region->append_intptr_t((intptr_t)(*p));
   }
 
   void do_bool(bool *p) {
-    void* ptr = (void*)(uintx(*p));
-    do_ptr(&ptr);
+    _dump_region->append_intptr_t((intptr_t)(*p));
   }
 
   void do_tag(int tag) {
@@ -170,7 +169,7 @@
   bool reading() const { return true; }
 };
 
-#endif
+#endif // INCLUDE_CDS
 
 // Class Data Sharing Support
 class MetaspaceShared : AllStatic {
@@ -187,6 +186,7 @@
   static size_t  _i2i_entry_code_buffers_size;
   static size_t  _core_spaces_size;
   static void* _shared_metaspace_static_top;
+  static intx _relocation_delta;
  public:
   enum {
     // core archive spaces
@@ -194,11 +194,12 @@
     rw = 1,  // read-write shared space in the heap
     ro = 2,  // read-only shared space in the heap
     md = 3,  // miscellaneous data for initializing tables, etc.
-    num_core_spaces = 4, // number of non-string regions
-    num_non_heap_spaces = 4,
+    bm = 4,  // relocation bitmaps (freed after file mapping is finished)
+    num_core_region = 4,
+    num_non_heap_spaces = 5,
 
     // mapped java heap regions
-    first_closed_archive_heap_region = md + 1,
+    first_closed_archive_heap_region = bm + 1,
     max_closed_archive_heap_region = 2,
     last_closed_archive_heap_region = first_closed_archive_heap_region + max_closed_archive_heap_region - 1,
     first_open_archive_heap_region = last_closed_archive_heap_region + 1,
@@ -220,16 +221,14 @@
     CDS_ONLY(return &_shared_rs);
     NOT_CDS(return NULL);
   }
+
+  static void set_shared_rs(ReservedSpace rs) {
+    CDS_ONLY(_shared_rs = rs);
+  }
+
   static void commit_shared_space_to(char* newtop) NOT_CDS_RETURN;
-  static size_t core_spaces_size() {
-    assert(DumpSharedSpaces || UseSharedSpaces, "sanity");
-    assert(_core_spaces_size != 0, "sanity");
-    return _core_spaces_size;
-  }
   static void initialize_dumptime_shared_and_meta_spaces() NOT_CDS_RETURN;
   static void initialize_runtime_shared_and_meta_spaces() NOT_CDS_RETURN;
-  static char* initialize_dynamic_runtime_shared_spaces(
-                     char* static_start, char* static_end) NOT_CDS_RETURN_(NULL);
   static void post_initialize(TRAPS) NOT_CDS_RETURN;
 
   // Delta of this object from SharedBaseAddress
@@ -245,22 +244,25 @@
   static void set_archive_loading_failed() {
     _archive_loading_failed = true;
   }
+  static bool is_in_output_space(void* ptr) {
+    assert(DumpSharedSpaces, "must be");
+    return shared_rs()->contains(ptr);
+  }
+
   static bool map_shared_spaces(FileMapInfo* mapinfo) NOT_CDS_RETURN_(false);
   static void initialize_shared_spaces() NOT_CDS_RETURN;
 
   // Return true if given address is in the shared metaspace regions (i.e., excluding any
   // mapped shared heap regions.)
   static bool is_in_shared_metaspace(const void* p) {
-    // If no shared metaspace regions are mapped, MetaspceObj::_shared_metaspace_{base,top} will
-    // both be NULL and all values of p will be rejected quickly.
-    return (p < MetaspaceObj::shared_metaspace_top() && p >= MetaspaceObj::shared_metaspace_base());
+    return MetaspaceObj::is_shared((const MetaspaceObj*)p);
   }
 
   static address shared_metaspace_top() {
     return (address)MetaspaceObj::shared_metaspace_top();
   }
 
-  static void set_shared_metaspace_range(void* base, void* top) NOT_CDS_RETURN;
+  static void set_shared_metaspace_range(void* base, void *static_top, void* top) NOT_CDS_RETURN;
 
   // Return true if given address is in the shared region corresponding to the idx
   static bool is_in_shared_region(const void* p, int idx) NOT_CDS_RETURN_(false);
@@ -298,8 +300,8 @@
   static void link_and_cleanup_shared_classes(TRAPS);
 
 #if INCLUDE_CDS
-  static ReservedSpace* reserve_shared_rs(size_t size, size_t alignment,
-                                          bool large, char* requested_address);
+  static ReservedSpace reserve_shared_space(size_t size, char* requested_address = NULL);
+  static size_t reserved_space_alignment();
   static void init_shared_dump_space(DumpRegion* first_space, address first_space_bottom = NULL);
   static DumpRegion* misc_code_dump_space();
   static DumpRegion* read_write_dump_space();
@@ -342,11 +344,35 @@
   }
   static void relocate_klass_ptr(oop o);
 
-  static Klass* get_relocated_klass(Klass *k);
+  static Klass* get_relocated_klass(Klass *k, bool is_final=false);
 
   static intptr_t* fix_cpp_vtable_for_dynamic_archive(MetaspaceObj::Type msotype, address obj);
+  static void initialize_ptr_marker(CHeapBitMap* ptrmap);
 
+  // Non-zero if the archive(s) need to be mapped a non-default location due to ASLR.
+  static intx relocation_delta() { return _relocation_delta; }
+  static intx final_delta();
+  static bool use_windows_memory_mapping() {
+    const bool is_windows = (NOT_WINDOWS(false) WINDOWS_ONLY(true));
+    //const bool is_windows = true; // enable this to allow testing the windows mmap semantics on Linux, etc.
+    return is_windows;
+  }
 private:
   static void read_extra_data(const char* filename, TRAPS) NOT_CDS_RETURN;
+  static FileMapInfo* open_static_archive();
+  static FileMapInfo* open_dynamic_archive();
+  static MapArchiveResult map_archives(FileMapInfo* static_mapinfo, FileMapInfo* dynamic_mapinfo,
+                                       bool use_requested_addr);
+  static char* reserve_address_space_for_archives(FileMapInfo* static_mapinfo,
+                                                  FileMapInfo* dynamic_mapinfo,
+                                                  bool use_requested_addr,
+                                                  ReservedSpace& main_rs,
+                                                  ReservedSpace& archive_space_rs,
+                                                  ReservedSpace& class_space_rs);
+  static void release_reserved_spaces(ReservedSpace& main_rs,
+                                      ReservedSpace& archive_space_rs,
+                                      ReservedSpace& class_space_rs);
+  static MapArchiveResult map_archive(FileMapInfo* mapinfo, char* mapped_base_address, ReservedSpace rs);
+  static void unmap_archive(FileMapInfo* mapinfo);
 };
 #endif // SHARE_MEMORY_METASPACESHARED_HPP
--- a/src/hotspot/share/memory/universe.cpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/memory/universe.cpp	Wed Nov 13 16:36:54 2019 -0800
@@ -85,18 +85,24 @@
 #include "utilities/ostream.hpp"
 #include "utilities/preserveException.hpp"
 
+#define PRIMITIVE_MIRRORS_DO(func) \
+  func(_int_mirror)    \
+  func(_float_mirror)  \
+  func(_double_mirror) \
+  func(_byte_mirror)   \
+  func(_bool_mirror)   \
+  func(_char_mirror)   \
+  func(_long_mirror)   \
+  func(_short_mirror)  \
+  func(_void_mirror)
+
+#define DEFINE_PRIMITIVE_MIRROR(m) \
+    oop Universe::m  = NULL;
+
 // Known objects
+PRIMITIVE_MIRRORS_DO(DEFINE_PRIMITIVE_MIRROR)
 Klass* Universe::_typeArrayKlassObjs[T_LONG+1]        = { NULL /*, NULL...*/ };
 Klass* Universe::_objectArrayKlassObj                 = NULL;
-oop Universe::_int_mirror                             = NULL;
-oop Universe::_float_mirror                           = NULL;
-oop Universe::_double_mirror                          = NULL;
-oop Universe::_byte_mirror                            = NULL;
-oop Universe::_bool_mirror                            = NULL;
-oop Universe::_char_mirror                            = NULL;
-oop Universe::_long_mirror                            = NULL;
-oop Universe::_short_mirror                           = NULL;
-oop Universe::_void_mirror                            = NULL;
 oop Universe::_mirrors[T_VOID+1]                      = { NULL /*, NULL...*/ };
 oop Universe::_main_thread_group                      = NULL;
 oop Universe::_system_thread_group                    = NULL;
@@ -167,17 +173,11 @@
   }
 }
 
-void Universe::oops_do(OopClosure* f) {
+#define DO_PRIMITIVE_MIRROR(m) \
+  f->do_oop((oop*) &m);
 
-  f->do_oop((oop*) &_int_mirror);
-  f->do_oop((oop*) &_float_mirror);
-  f->do_oop((oop*) &_double_mirror);
-  f->do_oop((oop*) &_byte_mirror);
-  f->do_oop((oop*) &_bool_mirror);
-  f->do_oop((oop*) &_char_mirror);
-  f->do_oop((oop*) &_long_mirror);
-  f->do_oop((oop*) &_short_mirror);
-  f->do_oop((oop*) &_void_mirror);
+void Universe::oops_do(OopClosure* f) {
+  PRIMITIVE_MIRRORS_DO(DO_PRIMITIVE_MIRROR);
 
   for (int i = T_BOOLEAN; i < T_VOID+1; i++) {
     f->do_oop((oop*) &_mirrors[i]);
@@ -231,6 +231,13 @@
   _do_stack_walk_cache->metaspace_pointers_do(it);
 }
 
+#define ASSERT_MIRROR_NULL(m) \
+  assert(m == NULL, "archived mirrors should be NULL");
+
+#define SERIALIZE_MIRROR(m) \
+  f->do_oop(&m); \
+  if (m != NULL) { java_lang_Class::update_archived_primitive_mirror_native_pointers(m); }
+
 // Serialize metadata and pointers to primitive type mirrors in and out of CDS archive
 void Universe::serialize(SerializeClosure* f) {
 
@@ -239,25 +246,12 @@
   }
 
   f->do_ptr((void**)&_objectArrayKlassObj);
+
 #if INCLUDE_CDS_JAVA_HEAP
-#ifdef ASSERT
-  if (DumpSharedSpaces && !HeapShared::is_heap_object_archiving_allowed()) {
-    assert(_int_mirror == NULL    && _float_mirror == NULL &&
-           _double_mirror == NULL && _byte_mirror == NULL  &&
-           _bool_mirror == NULL   && _char_mirror == NULL  &&
-           _long_mirror == NULL   && _short_mirror == NULL &&
-           _void_mirror == NULL, "mirrors should be NULL");
-  }
-#endif
-  f->do_oop(&_int_mirror);
-  f->do_oop(&_float_mirror);
-  f->do_oop(&_double_mirror);
-  f->do_oop(&_byte_mirror);
-  f->do_oop(&_bool_mirror);
-  f->do_oop(&_char_mirror);
-  f->do_oop(&_long_mirror);
-  f->do_oop(&_short_mirror);
-  f->do_oop(&_void_mirror);
+  DEBUG_ONLY(if (DumpSharedSpaces && !HeapShared::is_heap_object_archiving_allowed()) {
+      PRIMITIVE_MIRRORS_DO(ASSERT_MIRROR_NULL);
+    });
+  PRIMITIVE_MIRRORS_DO(SERIALIZE_MIRROR);
 #endif
 
   f->do_ptr((void**)&_the_array_interfaces_array);
@@ -419,18 +413,18 @@
   #endif
 }
 
+#define ASSERT_MIRROR_NOT_NULL(m) \
+  assert(m != NULL, "archived mirrors should not be NULL");
+
 void Universe::initialize_basic_type_mirrors(TRAPS) {
 #if INCLUDE_CDS_JAVA_HEAP
     if (UseSharedSpaces &&
         HeapShared::open_archive_heap_region_mapped() &&
         _int_mirror != NULL) {
       assert(HeapShared::is_heap_object_archiving_allowed(), "Sanity");
-      assert(_float_mirror != NULL && _double_mirror != NULL &&
-             _byte_mirror  != NULL && _byte_mirror   != NULL &&
-             _bool_mirror  != NULL && _char_mirror   != NULL &&
-             _long_mirror  != NULL && _short_mirror  != NULL &&
-             _void_mirror  != NULL, "Sanity");
+      PRIMITIVE_MIRRORS_DO(ASSERT_MIRROR_NOT_NULL);
     } else
+      // _int_mirror could be NULL if archived heap is not mapped.
 #endif
     {
       _int_mirror     =
--- a/src/hotspot/share/oops/constMethod.cpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/oops/constMethod.cpp	Wed Nov 13 16:36:54 2019 -0800
@@ -420,6 +420,8 @@
   if (has_default_annotations()) {
       it->push(default_annotations_addr());
   }
+  ConstMethod* this_ptr = this;
+  it->push_method_entry(&this_ptr, (intptr_t*)&_adapter_trampoline);
 }
 
 // Printing
--- a/src/hotspot/share/oops/instanceKlass.cpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/oops/instanceKlass.cpp	Wed Nov 13 16:36:54 2019 -0800
@@ -1577,11 +1577,30 @@
 }
 #endif
 
-static int binary_search(const Array<Method*>* methods, const Symbol* name) {
+bool InstanceKlass::_disable_method_binary_search = false;
+
+int InstanceKlass::quick_search(const Array<Method*>* methods, const Symbol* name) {
   int len = methods->length();
-  // methods are sorted, so do binary search
   int l = 0;
   int h = len - 1;
+
+  if (_disable_method_binary_search) {
+    // At the final stage of dynamic dumping, the methods array may not be sorted
+    // by ascending addresses of their names, so we can't use binary search anymore.
+    // However, methods with the same name are still laid out consecutively inside the
+    // methods array, so let's look for the first one that matches.
+    assert(DynamicDumpSharedSpaces, "must be");
+    while (l <= h) {
+      Method* m = methods->at(l);
+      if (m->name() == name) {
+        return l;
+      }
+      l ++;
+    }
+    return -1;
+  }
+
+  // methods are sorted by ascending addresses of their names, so do binary search
   while (l <= h) {
     int mid = (l + h) >> 1;
     Method* m = methods->at(mid);
@@ -1733,7 +1752,7 @@
   const bool skipping_overpass = (overpass_mode == skip_overpass);
   const bool skipping_static = (static_mode == skip_static);
   const bool skipping_private = (private_mode == skip_private);
-  const int hit = binary_search(methods, name);
+  const int hit = quick_search(methods, name);
   if (hit != -1) {
     const Method* const m = methods->at(hit);
 
@@ -1784,7 +1803,7 @@
                                        const Symbol* name,
                                        int* end_ptr) {
   assert(end_ptr != NULL, "just checking");
-  int start = binary_search(methods, name);
+  int start = quick_search(methods, name);
   int end = start + 1;
   if (start != -1) {
     while (start - 1 >= 0 && (methods->at(start - 1))->name() == name) --start;
@@ -2365,6 +2384,7 @@
   _breakpoints = NULL;
   _previous_versions = NULL;
   _cached_class_file = NULL;
+  _jvmti_cached_class_field_map = NULL;
 #endif
 
   _init_thread = NULL;
@@ -2373,6 +2393,8 @@
   _oop_map_cache = NULL;
   // clear _nest_host to ensure re-load at runtime
   _nest_host = NULL;
+  _package_entry = NULL;
+  _dep_context_last_cleaned = 0;
 }
 
 void InstanceKlass::remove_java_mirror() {
--- a/src/hotspot/share/oops/instanceKlass.hpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/oops/instanceKlass.hpp	Wed Nov 13 16:36:54 2019 -0800
@@ -329,6 +329,8 @@
 
   friend class SystemDictionary;
 
+  static bool _disable_method_binary_search;
+
  public:
   u2 loader_type() {
     return _misc_flags & loader_type_bits();
@@ -564,6 +566,14 @@
   bool find_local_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const;
   bool find_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const;
 
+ private:
+  static int quick_search(const Array<Method*>* methods, const Symbol* name);
+
+ public:
+  static void disable_method_binary_search() {
+    _disable_method_binary_search = true;
+  }
+
   // find a local method (returns NULL if not found)
   Method* find_method(const Symbol* name, const Symbol* signature) const;
   static Method* find_method(const Array<Method*>* methods,
--- a/src/hotspot/share/oops/method.cpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/oops/method.cpp	Wed Nov 13 16:36:54 2019 -0800
@@ -332,18 +332,21 @@
   return align_metadata_size(header_size() + extra_words);
 }
 
-
 Symbol* Method::klass_name() const {
   return method_holder()->name();
 }
 
-
 void Method::metaspace_pointers_do(MetaspaceClosure* it) {
   log_trace(cds)("Iter(Method): %p", this);
 
   it->push(&_constMethod);
   it->push(&_method_data);
   it->push(&_method_counters);
+
+  Method* this_ptr = this;
+  it->push_method_entry(&this_ptr, (intptr_t*)&_i2i_entry);
+  it->push_method_entry(&this_ptr, (intptr_t*)&_from_compiled_entry);
+  it->push_method_entry(&this_ptr, (intptr_t*)&_from_interpreted_entry);
 }
 
 // Attempt to return method oop to original state.  Clear any pointers
@@ -1741,12 +1744,15 @@
 
 // This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
 // default_methods also uses this without the ordering for fast find_method
-void Method::sort_methods(Array<Method*>* methods, bool set_idnums) {
+void Method::sort_methods(Array<Method*>* methods, bool set_idnums, method_comparator_func func) {
   int length = methods->length();
   if (length > 1) {
+    if (func == NULL) {
+      func = method_comparator;
+    }
     {
       NoSafepointVerifier nsv;
-      QuickSort::sort(methods->data(), length, method_comparator, /*idempotent=*/false);
+      QuickSort::sort(methods->data(), length, func, /*idempotent=*/false);
     }
     // Reset method ordering
     if (set_idnums) {
--- a/src/hotspot/share/oops/method.hpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/oops/method.hpp	Wed Nov 13 16:36:54 2019 -0800
@@ -1006,8 +1006,10 @@
   void print_name(outputStream* st = tty)        PRODUCT_RETURN; // prints as "virtual void foo(int)"
 #endif
 
+  typedef int (*method_comparator_func)(Method* a, Method* b);
+
   // Helper routine used for method sorting
-  static void sort_methods(Array<Method*>* methods, bool set_idnums = true);
+  static void sort_methods(Array<Method*>* methods, bool set_idnums = true, method_comparator_func func = NULL);
 
   // Deallocation function for redefine classes or if an error occurs
   void deallocate_contents(ClassLoaderData* loader_data);
--- a/src/hotspot/share/runtime/arguments.cpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/runtime/arguments.cpp	Wed Nov 13 16:36:54 2019 -0800
@@ -85,6 +85,7 @@
 bool   Arguments::_ClipInlining                 = ClipInlining;
 intx   Arguments::_Tier3InvokeNotifyFreqLog     = Tier3InvokeNotifyFreqLog;
 intx   Arguments::_Tier4InvocationThreshold     = Tier4InvocationThreshold;
+size_t Arguments::_SharedBaseAddress            = SharedBaseAddress;
 
 bool   Arguments::_enable_preview               = false;
 
@@ -2274,6 +2275,9 @@
     Arguments::_Tier4InvocationThreshold = Tier4InvocationThreshold;
   }
 
+  // CDS dumping always write the archive to the default value of SharedBaseAddress.
+  Arguments::_SharedBaseAddress = SharedBaseAddress;
+
   // Setup flags for mixed which is the default
   set_mode_flags(_mixed);
 
--- a/src/hotspot/share/runtime/arguments.hpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/runtime/arguments.hpp	Wed Nov 13 16:36:54 2019 -0800
@@ -481,6 +481,7 @@
 
   static char*  SharedArchivePath;
   static char*  SharedDynamicArchivePath;
+  static size_t _SharedBaseAddress; // The default value specified in globals.hpp
   static int num_archives(const char* archive_path) NOT_CDS_RETURN_(0);
   static void extract_shared_archive_paths(const char* archive_path,
                                          char** base_archive_path,
@@ -563,7 +564,7 @@
 
   static const char* GetSharedArchivePath() { return SharedArchivePath; }
   static const char* GetSharedDynamicArchivePath() { return SharedDynamicArchivePath; }
-
+  static size_t default_SharedBaseAddress() { return _SharedBaseAddress; }
   // Java launcher properties
   static void process_sun_java_launcher_properties(JavaVMInitArgs* args);
 
--- a/src/hotspot/share/runtime/globals.hpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/runtime/globals.hpp	Wed Nov 13 16:36:54 2019 -0800
@@ -2430,6 +2430,14 @@
   product(ccstr, ExtraSharedClassListFile, NULL,                            \
           "Extra classlist for building the CDS archive file")              \
                                                                             \
+  diagnostic(intx, ArchiveRelocationMode, 0,                                \
+           "(0) first map at preferred address, and if "                    \
+           "unsuccessful, map at alternative address (default); "           \
+           "(1) always map at alternative address; "                        \
+           "(2) always map at preferred address, and if unsuccessful, "     \
+           "do not map the archive")                                        \
+           range(0, 2)                                                      \
+                                                                            \
   experimental(size_t, ArrayAllocatorMallocLimit,                           \
           SOLARIS_ONLY(64*K) NOT_SOLARIS((size_t)-1),                       \
           "Allocation less than this value will be allocated "              \
--- a/src/hotspot/share/runtime/vmStructs.cpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/hotspot/share/runtime/vmStructs.cpp	Wed Nov 13 16:36:54 2019 -0800
@@ -1103,7 +1103,7 @@
   CDS_ONLY(nonstatic_field(FileMapInfo,        _header,                   FileMapHeader*))                                           \
   CDS_ONLY(   static_field(FileMapInfo,        _current_info,             FileMapInfo*))                                             \
   CDS_ONLY(nonstatic_field(FileMapHeader,      _space[0],                 CDSFileMapRegion))                                         \
-  CDS_ONLY(nonstatic_field(CDSFileMapRegion,   _addr._base,               char*))                                                    \
+  CDS_ONLY(nonstatic_field(CDSFileMapRegion,   _mapped_base,              char*))                                                    \
   CDS_ONLY(nonstatic_field(CDSFileMapRegion,   _used,                     size_t))                                                   \
                                                                                                                                      \
   /******************/                                                                                                               \
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java	Wed Nov 13 16:36:54 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -70,7 +70,7 @@
 
     // SpaceInfo
     type = db.lookupType("CDSFileMapRegion");
-    long mdRegionBaseAddressOffset = type.getField("_addr._base").getOffset();
+    long mdRegionBaseAddressOffset = type.getField("_mapped_base").getOffset();
     mdRegionBaseAddress = (mdSpaceValue.addOffsetTo(mdRegionBaseAddressOffset)).getAddressAt(0);
     long mdRegionSizeOffset = type.getField("_used").getOffset();
     long mdRegionSize = (mdSpaceValue.addOffsetTo(mdRegionSizeOffset)).getAddressAt(0).asLongValue();
--- a/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/jdk.hotspot.agent/share/native/libsaproc/ps_core_common.c	Wed Nov 13 16:36:54 2019 -0800
@@ -261,6 +261,7 @@
 // mangled name of Arguments::SharedArchivePath
 #define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE"
 #define USE_SHARED_SPACES_SYM "UseSharedSpaces"
+#define SHARED_BASE_ADDRESS_SYM "SharedBaseAddress"
 #define LIBJVM_NAME "/libjvm.so"
 #endif
 
@@ -268,6 +269,7 @@
 // mangled name of Arguments::SharedArchivePath
 #define SHARED_ARCHIVE_PATH_SYM "__ZN9Arguments17SharedArchivePathE"
 #define USE_SHARED_SPACES_SYM "_UseSharedSpaces"
+#define SHARED_BASE_ADDRESS_SYM "_SharedBaseAddress"
 #define LIBJVM_NAME "/libjvm.dylib"
 #endif
 
@@ -281,7 +283,8 @@
       char classes_jsa[PATH_MAX];
       CDSFileMapHeaderBase header;
       int fd = -1;
-      uintptr_t base = 0, useSharedSpacesAddr = 0;
+      uintptr_t useSharedSpacesAddr = 0;
+      uintptr_t sharedBaseAddressAddr = 0, sharedBaseAddress = 0;
       uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 0;
       jboolean useSharedSpaces = 0;
       int m;
@@ -308,6 +311,17 @@
         return true;
       }
 
+      sharedBaseAddressAddr = lookup_symbol(ph, jvm_name, SHARED_BASE_ADDRESS_SYM);
+      if (sharedBaseAddressAddr == 0) {
+        print_debug("can't lookup 'SharedBaseAddress' flag\n");
+        return false;
+      }
+
+      if (read_pointer(ph, sharedBaseAddressAddr, &sharedBaseAddress) != true) {
+        print_debug("can't read the value of 'SharedBaseAddress' flag\n");
+        return false;
+      }
+
       sharedArchivePathAddrAddr = lookup_symbol(ph, jvm_name, SHARED_ARCHIVE_PATH_SYM);
       if (sharedArchivePathAddrAddr == 0) {
         print_debug("can't lookup shared archive path symbol\n");
@@ -363,16 +377,19 @@
       ph->core->classes_jsa_fd = fd;
       // add read-only maps from classes.jsa to the list of maps
       for (m = 0; m < NUM_CDS_REGIONS; m++) {
-        if (header._space[m]._read_only) {
+        if (header._space[m]._read_only &&
+            !header._space[m]._is_heap_region &&
+            !header._space[m]._is_bitmap_region) {
           // With *some* linux versions, the core file doesn't include read-only mmap'ed
           // files regions, so let's add them here. This is harmless if the core file also
           // include these regions.
-          base = (uintptr_t) header._space[m]._addr._base;
+          uintptr_t base = sharedBaseAddress + (uintptr_t) header._space[m]._mapping_offset;
+          size_t size = header._space[m]._used;
           // no need to worry about the fractional pages at-the-end.
           // possible fractional pages are handled by core_read_data.
           add_class_share_map_info(ph, (off_t) header._space[m]._file_offset,
-                                   base, (size_t) header._space[m]._used);
-          print_debug("added a share archive map at 0x%lx\n", base);
+                                   base, size);
+          print_debug("added a share archive map [%d] at 0x%lx (size 0x%lx bytes)\n", m, base, size);
         }
       }
       return true;
--- a/src/jdk.hotspot.agent/solaris/native/libsaproc/saproc.cpp	Thu Nov 14 10:02:52 2019 +0800
+++ b/src/jdk.hotspot.agent/solaris/native/libsaproc/saproc.cpp	Wed Nov 13 16:36:54 2019 -0800
@@ -538,9 +538,11 @@
 }
 
 #define USE_SHARED_SPACES_SYM   "UseSharedSpaces"
+#define SHARED_BASE_ADDRESS_SYM "SharedBaseAddress"
 // mangled symbol name for Arguments::SharedArchivePath
 #define SHARED_ARCHIVE_PATH_SYM "__1cJArgumentsRSharedArchivePath_"
 
+static uintptr_t sharedBaseAddress = 0;
 static int
 init_classsharing_workaround(void *cd, const prmap_t* pmap, const char* obj_name) {
   Debugger* dbg = (Debugger*) cd;
@@ -577,6 +579,19 @@
     return 1;
   }
 
+  psaddr_t sharedBaseAddressAddr = 0;
+  ps_pglobal_lookup(ph, jvm_name, SHARED_ARCHIVE_PATH_SYM, &sharedBaseAddressAddr);
+  if (sharedBaseAddressAddr == 0) {
+    print_debug("can't find symbol 'SharedBaseAddress'\n");
+    THROW_NEW_DEBUGGER_EXCEPTION_("can't find 'SharedBaseAddress' flag\n", 1);
+  }
+
+  sharedBaseAddress = 0;
+  if (read_pointer(ph, sharedBaseAddressAddr, &sharedBaseAddress) != true) {
+    print_debug("can't read the value of 'SharedBaseAddress' flag\n");
+    THROW_NEW_DEBUGGER_EXCEPTION_("can't get SharedBaseAddress from debuggee", 1);
+  }
+
   char classes_jsa[PATH_MAX];
   psaddr_t sharedArchivePathAddrAddr = 0;
   ps_pglobal_lookup(ph, jvm_name, SHARED_ARCHIVE_PATH_SYM, &sharedArchivePathAddrAddr);
@@ -648,9 +663,14 @@
 
   if (_libsaproc_debug) {
     for (int m = 0; m < NUM_CDS_REGIONS; m++) {
-       print_debug("shared file offset %d mapped at 0x%lx, size = %ld, read only? = %d\n",
-          pheader->_space[m]._file_offset, pheader->_space[m]._addr._base,
-          pheader->_space[m]._used, pheader->_space[m]._read_only);
+      if (!pheader->_space[m]._is_heap_region &&
+          !pheader->_space[m]._is_bitmap_region) {
+        jlong mapping_offset = pheader->_space[m]._mapping_offset;
+        jlong baseAddress = mapping_offset + (jlong)sharedBaseAddress;
+        print_debug("shared file offset %d mapped at 0x%lx, size = %ld, read only? = %d\n",
+                    pheader->_space[m]._file_offset, baseAddress,
+                    pheader->_space[m]._used, pheader->_space[m]._read_only);
+      }
     }
   }
 
@@ -1052,11 +1072,14 @@
         // We can skip the non-read-only maps. These are mapped as MAP_PRIVATE
         // and hence will be read by libproc. Besides, the file copy may be
         // stale because the process might have modified those pages.
-        if (pheader->_space[m]._read_only) {
-          jlong baseAddress = (jlong) (uintptr_t) pheader->_space[m]._addr._base;
-          size_t usedSize = pheader->_space[m]._used;
-          if (address >= baseAddress && address < (baseAddress + usedSize)) {
-            // the given address falls in this shared heap area
+        if (pheader->_space[m]._read_only &&
+            !pheader->_space[m]._is_heap_region &&
+            !pheader->_space[m]._is_bitmap_region) {
+         jlong mapping_offset = (jlong) (uintptr_t) pheader->_space[m]._mapping_offset;
+         jlong baseAddress = mapping_offset + (jlong)sharedBaseAddress;
+         size_t usedSize = pheader->_space[m]._used;
+         if (address >= baseAddress && address < (baseAddress + usedSize)) {
+            // the given address falls in this shared metadata area
             print_debug("found shared map at 0x%lx\n", (long) baseAddress);
 
 
--- a/test/hotspot/jtreg/TEST.groups	Thu Nov 14 10:02:52 2019 +0800
+++ b/test/hotspot/jtreg/TEST.groups	Wed Nov 13 16:36:54 2019 -0800
@@ -322,6 +322,7 @@
  -runtime/cds/appcds/javaldr/GCSharedStringsDuringDump.java \
  -runtime/cds/appcds/javaldr/HumongousDuringDump.java \
  -runtime/cds/appcds/sharedStrings \
+ -runtime/cds/appcds/ArchiveRelocationTest.java \
  -runtime/cds/appcds/DumpClassList.java \
  -runtime/cds/appcds/ExtraSymbols.java \
  -runtime/cds/appcds/LongClassListPath.java \
@@ -332,6 +333,15 @@
  -runtime/cds/appcds/UnusedCPDuringDump.java \
  -runtime/cds/appcds/VerifierTest_1B.java
 
+hotspot_cds_relocation = \
+  gc/g1/TestSharedArchiveWithPreTouch.java \
+  runtime/cds \
+  runtime/modules/ModulesSymLink.java \
+  runtime/modules/PatchModule/PatchModuleCDS.java \
+  runtime/modules/PatchModule/PatchModuleClassList.java \
+  runtime/NMT \
+  serviceability/sa
+
 # A subset of AppCDS tests to be run in tier1
 tier1_runtime_appcds = \
   runtime/cds/appcds/HelloTest.java \
--- a/test/hotspot/jtreg/runtime/cds/SpaceUtilizationCheck.java	Thu Nov 14 10:02:52 2019 +0800
+++ b/test/hotspot/jtreg/runtime/cds/SpaceUtilizationCheck.java	Wed Nov 13 16:36:54 2019 -0800
@@ -73,8 +73,8 @@
                 Matcher matcher = pattern.matcher(line);
                 if (matcher.find()) {
                     String name = matcher.group(1);
-                    if (name.equals("s0") || name.equals("s1")) {
-                      // String regions are listed at the end and they may not be fully occupied.
+                    if (name.equals("bm")) {
+                      // Bitmap space does not have a requested address.
                       break;
                     } else {
                       System.out.println("Checking " + name + " in : " + line);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java	Wed Nov 13 16:36:54 2019 -0800
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2019, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @comment the test uses -XX:ArchiveRelocationMode=1 to force relocation.
+ * @requires vm.cds
+ * @summary Testing relocation of CDS archive (during both dump time and run time)
+ * @comment JDK-8231610 Relocate the CDS archive if it cannot be mapped to the requested address
+ * @bug 8231610
+ * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes
+ * @build Hello
+ * @run driver ClassFileInstaller -jar hello.jar Hello
+ * @run driver ArchiveRelocationTest
+ */
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jtreg.SkippedException;
+
+public class ArchiveRelocationTest {
+    public static void main(String... args) throws Exception {
+        try {
+            test(true,  false);
+            test(false, true);
+            test(true,  true);
+        } catch (SkippedException s) {
+            s.printStackTrace();
+            throw new RuntimeException("Archive mapping should always succeed after JDK-8231610 (did the machine run out of memory?)");
+        }
+    }
+
+    static int caseCount = 0;
+
+    // dump_reloc - force relocation of archive during dump time?
+    // run_reloc  - force relocation of archive during run time?
+    static void test(boolean dump_reloc, boolean run_reloc) throws Exception {
+        caseCount += 1;
+        System.out.println("============================================================");
+        System.out.println("case = " + caseCount + ", dump = " + dump_reloc
+                           + ", run = " + run_reloc);
+        System.out.println("============================================================");
+
+
+        String appJar = ClassFileInstaller.getJarPath("hello.jar");
+        String mainClass = "Hello";
+        String forceRelocation = "-XX:ArchiveRelocationMode=1";
+        String dumpRelocArg = dump_reloc ? forceRelocation : "-showversion";
+        String runRelocArg  = run_reloc  ? forceRelocation : "-showversion";
+        String logArg = "-Xlog:cds=debug,cds+reloc=debug";
+        String unlockArg = "-XX:+UnlockDiagnosticVMOptions";
+
+        OutputAnalyzer out = TestCommon.dump(appJar,
+                                             TestCommon.list(mainClass),
+                                             unlockArg, dumpRelocArg, logArg);
+        if (dump_reloc) {
+            out.shouldContain("ArchiveRelocationMode == 1: always allocate class space at an alternative address");
+            out.shouldContain("Relocating archive from");
+        }
+
+        TestCommon.run("-cp", appJar, unlockArg, runRelocArg, logArg,  mainClass)
+            .assertNormalExit(output -> {
+                    if (run_reloc) {
+                        output.shouldContain("ArchiveRelocationMode == 1: always map archive(s) at an alternative address");
+                        output.shouldContain("runtime archive relocation start");
+                        output.shouldContain("runtime archive relocation done");
+                    }
+                });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveRelocationTest.java	Wed Nov 13 16:36:54 2019 -0800
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2019, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @comment the test uses -XX:ArchiveRelocationMode=1 to force relocation.
+ * @requires vm.cds
+ * @summary Testing relocation of dynamic CDS archive (during both dump time and run time)
+ * @comment JDK-8231610 Relocate the CDS archive if it cannot be mapped to the requested address
+ * @bug 8231610
+ * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes
+ * @build Hello
+ * @run driver ClassFileInstaller -jar hello.jar Hello
+ * @run driver DynamicArchiveRelocationTest
+ */
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jtreg.SkippedException;
+
+public class DynamicArchiveRelocationTest extends DynamicArchiveTestBase {
+    public static void main(String... args) throws Exception {
+        try {
+            testOuter(false);
+            testOuter(true);
+        } catch (SkippedException s) {
+            s.printStackTrace();
+            throw new RuntimeException("Archive mapping should always succeed after JDK-8231610 (did the machine run out of memory?)");
+        }
+    }
+
+    static void testOuter(boolean dump_base_reloc) throws Exception {
+        testInner(dump_base_reloc, true,  false);
+        testInner(dump_base_reloc, false, true);
+        testInner(dump_base_reloc, true,  true);
+    }
+
+    static boolean dump_base_reloc, dump_top_reloc, run_reloc;
+
+    // dump_base_reloc - force relocation of archive when dumping base archive
+    // dump_top_reloc  - force relocation of archive when dumping top  archive
+    // run_reloc       - force relocation of archive when running
+    static void testInner(boolean dump_base_reloc, boolean dump_top_reloc, boolean run_reloc) throws Exception {
+        DynamicArchiveRelocationTest.dump_base_reloc = dump_base_reloc;
+        DynamicArchiveRelocationTest.dump_top_reloc  = dump_top_reloc;
+        DynamicArchiveRelocationTest.run_reloc       = run_reloc;
+
+        runTest(DynamicArchiveRelocationTest::doTest);
+    }
+
+    static int caseCount = 0;
+    static void doTest() throws Exception {
+        caseCount += 1;
+        System.out.println("============================================================");
+        System.out.println("case = " + caseCount + ", base = " + dump_base_reloc
+                           + ", top = " + dump_top_reloc
+                           + ", run = " + run_reloc);
+        System.out.println("============================================================");
+
+        String appJar = ClassFileInstaller.getJarPath("hello.jar");
+        String mainClass = "Hello";
+        String forceRelocation = "-XX:ArchiveRelocationMode=1";
+        String dumpBaseRelocArg = dump_base_reloc ? forceRelocation : "-showversion";
+        String dumpTopRelocArg  = dump_top_reloc  ? forceRelocation : "-showversion";
+        String runRelocArg      = run_reloc       ? forceRelocation : "-showversion";
+        String logArg = "-Xlog:cds=debug,cds+reloc=debug";
+
+        String baseArchiveName = getNewArchiveName("base");
+        String topArchiveName  = getNewArchiveName("top");
+
+        String runtimeMsg1 = "ArchiveRelocationMode == 1: always map archive(s) at an alternative address";
+        String runtimeMsg2 = "runtime archive relocation start";
+        String runtimeMsg3 = "runtime archive relocation done";
+        String unlockArg = "-XX:+UnlockDiagnosticVMOptions";
+
+        // (1) Dump base archive (static)
+
+        OutputAnalyzer out = dumpBaseArchive(baseArchiveName, unlockArg, dumpBaseRelocArg, logArg);
+        if (dump_base_reloc) {
+            out.shouldContain("ArchiveRelocationMode == 1: always allocate class space at an alternative address");
+            out.shouldContain("Relocating archive from");
+        }
+
+        // (2) Dump top archive (dynamic)
+
+        dump2(baseArchiveName, topArchiveName,
+              unlockArg,
+              dumpTopRelocArg,
+              logArg,
+              "-cp", appJar, mainClass)
+            .assertNormalExit(output -> {
+                    if (dump_top_reloc) {
+                        output.shouldContain(runtimeMsg1);
+                        output.shouldContain(runtimeMsg2);
+                        output.shouldContain(runtimeMsg3);
+                    }
+                });
+
+        run2(baseArchiveName, topArchiveName,
+             unlockArg,
+             runRelocArg,
+             logArg,
+            "-cp", appJar, mainClass)
+            .assertNormalExit(output -> {
+                    if (run_reloc) {
+                        output.shouldContain(runtimeMsg1);
+                        output.shouldContain(runtimeMsg2);
+                        output.shouldContain(runtimeMsg3);
+                    }
+                });
+    }
+}
--- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java	Thu Nov 14 10:02:52 2019 +0800
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveTestBase.java	Wed Nov 13 16:36:54 2019 -0800
@@ -134,7 +134,7 @@
      * Dump the base archive. The JDK's default class list is used (unless otherwise specified
      * in cmdLineSuffix).
      */
-    public static void dumpBaseArchive(String baseArchiveName, String ... cmdLineSuffix)
+    public static OutputAnalyzer dumpBaseArchive(String baseArchiveName, String ... cmdLineSuffix)
         throws Exception
     {
         CDSOptions opts = new CDSOptions();
@@ -143,6 +143,7 @@
         opts.addSuffix("-Djava.class.path=");
         OutputAnalyzer out = CDSTestUtils.createArchive(opts);
         CDSTestUtils.checkDump(out);
+        return out;
     }
 
     /**