Merge
authorbobv
Thu, 30 Nov 2017 09:51:28 -0500
changeset 48162 464c63eb6d1f
parent 48161 fed0e4b11604 (current diff)
parent 48160 599f67f3c6d6 (diff)
child 48164 995ed4b92655
Merge
--- a/src/hotspot/os/aix/osThread_aix.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/os/aix/osThread_aix.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -25,6 +25,7 @@
 
 // no precompiled headers
 
+#include "memory/allocation.inline.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/os.hpp"
--- a/src/hotspot/os/aix/os_aix.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/os/aix/os_aix.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -2490,6 +2490,22 @@
   return false;
 }
 
+char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr, int file_desc) {
+  assert(file_desc >= 0, "file_desc is not valid");
+  char* result = NULL;
+
+  // Always round to os::vm_page_size(), which may be larger than 4K.
+  bytes = align_up(bytes, os::vm_page_size());
+  result = reserve_mmaped_memory(bytes, requested_addr, 0);
+
+  if (result != NULL) {
+    if (replace_existing_mapping_with_file_mapping(result, bytes, file_desc) == NULL) {
+      vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory"));
+    }
+  }
+  return result;
+}
+
 // Reserve memory at an arbitrary address, only if that area is
 // available (and not reserved for something else).
 char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
--- a/src/hotspot/os/bsd/osThread_bsd.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/os/bsd/osThread_bsd.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -23,6 +23,7 @@
  */
 
 // no precompiled headers
+#include "memory/allocation.inline.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/osThread.hpp"
 
--- a/src/hotspot/os/bsd/os_bsd.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/os/bsd/os_bsd.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -2350,6 +2350,17 @@
   return UseHugeTLBFS;
 }
 
+char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr, int file_desc) {
+  assert(file_desc >= 0, "file_desc is not valid");
+  char* result = pd_attempt_reserve_memory_at(bytes, requested_addr);
+  if (result != NULL) {
+    if (replace_existing_mapping_with_file_mapping(result, bytes, file_desc) == NULL) {
+      vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory"));
+    }
+  }
+  return result;
+}
+
 // Reserve memory at an arbitrary address, only if that area is
 // available (and not reserved for something else).
 
--- a/src/hotspot/os/linux/osThread_linux.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/os/linux/osThread_linux.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -23,6 +23,7 @@
  */
 
 // no precompiled headers
+#include "memory/allocation.inline.hpp"
 #include "runtime/mutex.hpp"
 #include "runtime/osThread.hpp"
 
--- a/src/hotspot/os/linux/os_linux.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/os/linux/os_linux.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -130,6 +130,7 @@
 #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
 
 #define LARGEPAGES_BIT (1 << 6)
+#define DAX_SHARED_BIT (1 << 8)
 ////////////////////////////////////////////////////////////////////////////////
 // global variables
 julong os::Linux::_physical_memory = 0;
@@ -3370,10 +3371,13 @@
 //           effective only if the bit 2 is cleared)
 // - (bit 5) hugetlb private memory
 // - (bit 6) hugetlb shared memory
+// - (bit 7) dax private memory
+// - (bit 8) dax shared memory
 //
-static void set_coredump_filter(void) {
+static void set_coredump_filter(bool largepages, bool dax_shared) {
   FILE *f;
   long cdm;
+  bool filter_changed = false;
 
   if ((f = fopen("/proc/self/coredump_filter", "r+")) == NULL) {
     return;
@@ -3386,8 +3390,15 @@
 
   rewind(f);
 
-  if ((cdm & LARGEPAGES_BIT) == 0) {
+  if (largepages && (cdm & LARGEPAGES_BIT) == 0) {
     cdm |= LARGEPAGES_BIT;
+    filter_changed = true;
+  }
+  if (dax_shared && (cdm & DAX_SHARED_BIT) == 0) {
+    cdm |= DAX_SHARED_BIT;
+    filter_changed = true;
+  }
+  if (filter_changed) {
     fprintf(f, "%#lx", cdm);
   }
 
@@ -3526,7 +3537,7 @@
   size_t large_page_size = Linux::setup_large_page_size();
   UseLargePages          = Linux::setup_large_page_type(large_page_size);
 
-  set_coredump_filter();
+  set_coredump_filter(true /*largepages*/, false /*dax_shared*/);
 }
 
 #ifndef SHM_HUGETLB
@@ -3897,6 +3908,17 @@
   return UseTransparentHugePages || UseHugeTLBFS;
 }
 
+char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr, int file_desc) {
+  assert(file_desc >= 0, "file_desc is not valid");
+  char* result = pd_attempt_reserve_memory_at(bytes, requested_addr);
+  if (result != NULL) {
+    if (replace_existing_mapping_with_file_mapping(result, bytes, file_desc) == NULL) {
+      vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory"));
+    }
+  }
+  return result;
+}
+
 // Reserve memory at an arbitrary address, only if that area is
 // available (and not reserved for something else).
 
@@ -5008,6 +5030,9 @@
   // initialize thread priority policy
   prio_init();
 
+  if (!FLAG_IS_DEFAULT(AllocateHeapAt)) {
+    set_coredump_filter(false /*largepages*/, true /*dax_shared*/);
+  }
   return JNI_OK;
 }
 
--- a/src/hotspot/os/posix/os_posix.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/os/posix/os_posix.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -40,6 +40,7 @@
 #include <pthread.h>
 #include <semaphore.h>
 #include <signal.h>
+#include <sys/mman.h>
 #include <sys/resource.h>
 #include <sys/utsname.h>
 #include <time.h>
@@ -52,6 +53,20 @@
 #endif
 #define IS_VALID_PID(p) (p > 0 && p < MAX_PID)
 
+#ifndef MAP_ANONYMOUS
+  #define MAP_ANONYMOUS MAP_ANON
+#endif
+
+#define check_with_errno(check_type, cond, msg)                             \
+  do {                                                                      \
+    int err = errno;                                                        \
+    check_type(cond, "%s; error='%s' (errno=%s)", msg, os::strerror(err),   \
+               os::errno_name(err));                                        \
+} while (false)
+
+#define assert_with_errno(cond, msg)    check_with_errno(assert, cond, msg)
+#define guarantee_with_errno(cond, msg) check_with_errno(guarantee, cond, msg)
+
 // Check core dump limit and report possible place where core can be found
 void os::check_dump_limit(char* buffer, size_t bufferSize) {
   if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) {
@@ -145,10 +160,124 @@
   return;
 }
 
+int os::create_file_for_heap(const char* dir) {
+
+  const char name_template[] = "/jvmheap.XXXXXX";
+
+  char *fullname = (char*)os::malloc((strlen(dir) + strlen(name_template) + 1), mtInternal);
+  if (fullname == NULL) {
+    vm_exit_during_initialization(err_msg("Malloc failed during creation of backing file for heap (%s)", os::strerror(errno)));
+    return -1;
+  }
+  (void)strncpy(fullname, dir, strlen(dir)+1);
+  (void)strncat(fullname, name_template, strlen(name_template));
+
+  os::native_path(fullname);
+
+  sigset_t set, oldset;
+  int ret = sigfillset(&set);
+  assert_with_errno(ret == 0, "sigfillset returned error");
+
+  // set the file creation mask.
+  mode_t file_mode = S_IRUSR | S_IWUSR;
+
+  // create a new file.
+  int fd = mkstemp(fullname);
+
+  if (fd < 0) {
+    warning("Could not create file for heap with template %s", fullname);
+    os::free(fullname);
+    return -1;
+  }
+
+  // delete the name from the filesystem. When 'fd' is closed, the file (and space) will be deleted.
+  ret = unlink(fullname);
+  assert_with_errno(ret == 0, "unlink returned error");
+
+  os::free(fullname);
+  return fd;
+}
+
+static char* reserve_mmapped_memory(size_t bytes, char* requested_addr) {
+  char * addr;
+  int flags = MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS;
+  if (requested_addr != NULL) {
+    assert((uintptr_t)requested_addr % os::vm_page_size() == 0, "Requested address should be aligned to OS page size");
+    flags |= MAP_FIXED;
+  }
+
+  // Map reserved/uncommitted pages PROT_NONE so we fail early if we
+  // touch an uncommitted page. Otherwise, the read/write might
+  // succeed if we have enough swap space to back the physical page.
+  addr = (char*)::mmap(requested_addr, bytes, PROT_NONE,
+                       flags, -1, 0);
+
+  if (addr != MAP_FAILED) {
+    MemTracker::record_virtual_memory_reserve((address)addr, bytes, CALLER_PC);
+    return addr;
+  }
+  return NULL;
+}
+
+static int util_posix_fallocate(int fd, off_t offset, off_t len) {
+#ifdef __APPLE__
+  fstore_t store = { F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, len };
+  // First we try to get a continuous chunk of disk space
+  int ret = fcntl(fd, F_PREALLOCATE, &store);
+  if (ret == -1) {
+    // Maybe we are too fragmented, try to allocate non-continuous range
+    store.fst_flags = F_ALLOCATEALL;
+    ret = fcntl(fd, F_PREALLOCATE, &store);
+  }
+  if(ret != -1) {
+    return ftruncate(fd, len);
+  }
+  return -1;
+#else
+  return posix_fallocate(fd, offset, len);
+#endif
+}
+
+// Map the given address range to the provided file descriptor.
+char* os::map_memory_to_file(char* base, size_t size, int fd) {
+  assert(fd != -1, "File descriptor is not valid");
+
+  // allocate space for the file
+  if (util_posix_fallocate(fd, 0, (off_t)size) != 0) {
+    vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory."));
+    return NULL;
+  }
+
+  int prot = PROT_READ | PROT_WRITE;
+  int flags = MAP_SHARED;
+  if (base != NULL) {
+    flags |= MAP_FIXED;
+  }
+  char* addr = (char*)mmap(base, size, prot, flags, fd, 0);
+
+  if (addr == MAP_FAILED) {
+    return NULL;
+  }
+  if (base != NULL && addr != base) {
+    if (!os::release_memory(addr, size)) {
+      warning("Could not release memory on unsuccessful file mapping");
+     }
+    return NULL;
+  }
+  return addr;
+}
+
+char* os::replace_existing_mapping_with_file_mapping(char* base, size_t size, int fd) {
+  assert(fd != -1, "File descriptor is not valid");
+  assert(base != NULL, "Base cannot be NULL");
+
+  return map_memory_to_file(base, size, fd);
+}
+
 // Multiple threads can race in this code, and can remap over each other with MAP_FIXED,
 // so on posix, unmap the section at the start and at the end of the chunk that we mapped
 // rather than unmapping and remapping the whole chunk to get requested alignment.
-char* os::reserve_memory_aligned(size_t size, size_t alignment) {
+char* os::reserve_memory_aligned(size_t size, size_t alignment, int file_desc) {
   assert((alignment & (os::vm_allocation_granularity() - 1)) == 0,
       "Alignment must be a multiple of allocation granularity (page size)");
   assert((size & (alignment -1)) == 0, "size must be 'alignment' aligned");
@@ -156,7 +285,20 @@
   size_t extra_size = size + alignment;
   assert(extra_size >= size, "overflow, size is too large to allow alignment");
 
-  char* extra_base = os::reserve_memory(extra_size, NULL, alignment);
+  char* extra_base;
+  if (file_desc != -1) {
+    // For file mapping, we do not call os:reserve_memory(extra_size, NULL, alignment, file_desc) because
+    // we need to deal with shrinking of the file space later when we release extra memory after alignment.
+    // We also cannot called os:reserve_memory() with file_desc set to -1 because on aix we might get SHM memory.
+    // So here to call a helper function while reserve memory for us. After we have a aligned base,
+    // we will replace anonymous mapping with file mapping.
+    extra_base = reserve_mmapped_memory(extra_size, NULL);
+    if (extra_base != NULL) {
+      MemTracker::record_virtual_memory_reserve((address)extra_base, extra_size, CALLER_PC);
+    }
+  } else {
+    extra_base = os::reserve_memory(extra_size, NULL, alignment);
+  }
 
   if (extra_base == NULL) {
     return NULL;
@@ -183,6 +325,13 @@
       os::release_memory(extra_base + begin_offset + size, end_offset);
   }
 
+  if (file_desc != -1) {
+    // After we have an aligned address, we can replace anonymous mapping with file mapping
+    if (replace_existing_mapping_with_file_mapping(aligned_base, size, file_desc) == NULL) {
+      vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory"));
+    }
+    MemTracker::record_virtual_memory_commit((address)aligned_base, size, CALLER_PC);
+  }
   return aligned_base;
 }
 
@@ -1348,16 +1497,6 @@
   }
 }
 
-#define check_with_errno(check_type, cond, msg)                             \
-  do {                                                                      \
-    int err = errno;                                                        \
-    check_type(cond, "%s; error='%s' (errno=%s)", msg, os::strerror(err),   \
-               os::errno_name(err));                                        \
-} while (false)
-
-#define assert_with_errno(cond, msg)    check_with_errno(assert, cond, msg)
-#define guarantee_with_errno(cond, msg) check_with_errno(guarantee, cond, msg)
-
 // POSIX unamed semaphores are not supported on OS X.
 #ifndef __APPLE__
 
--- a/src/hotspot/os/solaris/os_solaris.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/os/solaris/os_solaris.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -2585,6 +2585,17 @@
   return addr;
 }
 
+char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr, int file_desc) {
+  assert(file_desc >= 0, "file_desc is not valid");
+  char* result = pd_attempt_reserve_memory_at(bytes, requested_addr);
+  if (result != NULL) {
+    if (replace_existing_mapping_with_file_mapping(result, bytes, file_desc) == NULL) {
+      vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory"));
+    }
+  }
+  return result;
+}
+
 // Reserve memory at an arbitrary address, only if that area is
 // available (and not reserved for something else).
 
--- a/src/hotspot/os/windows/os_windows.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/os/windows/os_windows.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -2904,6 +2904,75 @@
   UseLargePages = success;
 }
 
+int os::create_file_for_heap(const char* dir) {
+
+  const char name_template[] = "/jvmheap.XXXXXX";
+  char *fullname = (char*)os::malloc((strlen(dir) + strlen(name_template) + 1), mtInternal);
+  if (fullname == NULL) {
+    vm_exit_during_initialization(err_msg("Malloc failed during creation of backing file for heap (%s)", os::strerror(errno)));
+    return -1;
+  }
+
+  (void)strncpy(fullname, dir, strlen(dir)+1);
+  (void)strncat(fullname, name_template, strlen(name_template));
+
+  os::native_path(fullname);
+
+  char *path = _mktemp(fullname);
+  if (path == NULL) {
+    warning("_mktemp could not create file name from template %s (%s)", fullname, os::strerror(errno));
+    os::free(fullname);
+    return -1;
+  }
+
+  int fd = _open(path, O_RDWR | O_CREAT | O_TEMPORARY | O_EXCL, S_IWRITE | S_IREAD);
+
+  os::free(fullname);
+  if (fd < 0) {
+    warning("Problem opening file for heap (%s)", os::strerror(errno));
+    return -1;
+  }
+  return fd;
+}
+
+// If 'base' is not NULL, function will return NULL if it cannot get 'base'
+char* os::map_memory_to_file(char* base, size_t size, int fd) {
+  assert(fd != -1, "File descriptor is not valid");
+
+  HANDLE fh = (HANDLE)_get_osfhandle(fd);
+#ifdef _LP64
+  HANDLE fileMapping = CreateFileMapping(fh, NULL, PAGE_READWRITE,
+    (DWORD)(size >> 32), (DWORD)(size & 0xFFFFFFFF), NULL);
+#else
+  HANDLE fileMapping = CreateFileMapping(fh, NULL, PAGE_READWRITE,
+    0, (DWORD)size, NULL);
+#endif
+  if (fileMapping == NULL) {
+    if (GetLastError() == ERROR_DISK_FULL) {
+      vm_exit_during_initialization(err_msg("Could not allocate sufficient disk space for Java heap"));
+    }
+    else {
+      vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory"));
+    }
+
+    return NULL;
+  }
+
+  LPVOID addr = MapViewOfFileEx(fileMapping, FILE_MAP_WRITE, 0, 0, size, base);
+
+  CloseHandle(fileMapping);
+
+  return (char*)addr;
+}
+
+char* os::replace_existing_mapping_with_file_mapping(char* base, size_t size, int fd) {
+  assert(fd != -1, "File descriptor is not valid");
+  assert(base != NULL, "Base address cannot be NULL");
+
+  release_memory(base, size);
+  return map_memory_to_file(base, size, fd);
+}
+
 // On win32, one cannot release just a part of reserved memory, it's an
 // all or nothing deal.  When we split a reservation, we must break the
 // reservation into two reservations.
@@ -2923,7 +2992,7 @@
 // Multiple threads can race in this code but it's not possible to unmap small sections of
 // virtual space to get requested alignment, like posix-like os's.
 // Windows prevents multiple thread from remapping over each other so this loop is thread-safe.
-char* os::reserve_memory_aligned(size_t size, size_t alignment) {
+char* os::reserve_memory_aligned(size_t size, size_t alignment, int file_desc) {
   assert((alignment & (os::vm_allocation_granularity() - 1)) == 0,
          "Alignment must be a multiple of allocation granularity (page size)");
   assert((size & (alignment -1)) == 0, "size must be 'alignment' aligned");
@@ -2934,16 +3003,20 @@
   char* aligned_base = NULL;
 
   do {
-    char* extra_base = os::reserve_memory(extra_size, NULL, alignment);
+    char* extra_base = os::reserve_memory(extra_size, NULL, alignment, file_desc);
     if (extra_base == NULL) {
       return NULL;
     }
     // Do manual alignment
     aligned_base = align_up(extra_base, alignment);
 
-    os::release_memory(extra_base, extra_size);
-
-    aligned_base = os::reserve_memory(size, aligned_base);
+    if (file_desc != -1) {
+      os::unmap_memory(extra_base, extra_size);
+    } else {
+      os::release_memory(extra_base, extra_size);
+    }
+
+    aligned_base = os::reserve_memory(size, aligned_base, 0, file_desc);
 
   } while (aligned_base == NULL);
 
@@ -2989,6 +3062,11 @@
   return reserve_memory(bytes, requested_addr);
 }
 
+char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr, int file_desc) {
+  assert(file_desc >= 0, "file_desc is not valid");
+  return map_memory_to_file(requested_addr, bytes, file_desc);
+}
+
 size_t os::large_page_size() {
   return _large_page_size;
 }
--- a/src/hotspot/share/classfile/classListParser.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/classfile/classListParser.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -272,9 +272,11 @@
 // This function is used for loading classes for customized class loaders
 // during archive dumping.
 InstanceKlass* ClassListParser::load_class_from_source(Symbol* class_name, TRAPS) {
-#if !((defined(LINUX) && defined(X86) && defined(_LP64)) || \
-      (defined(SOLARIS) && defined(_LP64)))
-  // The only supported platforms are: (1) Linux/AMD64; (2) Solaris/64-bit
+#if !(defined(_LP64) && (defined(LINUX)|| defined(SOLARIS) || defined(AIX)))
+  // The only supported platforms are: (1) Linux/64-bit; (2) Solaris/64-bit; (3) AIX/64-bit
+  //
+  // This #if condition should be in sync with the areCustomLoadersSupportedForCDS
+  // method in test/lib/jdk/test/lib/Platform.java.
   error("AppCDS custom class loaders not supported on this platform");
 #endif
 
--- a/src/hotspot/share/classfile/klassFactory.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/classfile/klassFactory.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -25,7 +25,7 @@
 #ifndef SHARE_VM_CLASSFILE_KLASSFACTORY_HPP
 #define SHARE_VM_CLASSFILE_KLASSFACTORY_HPP
 
-#include "memory/allocation.inline.hpp"
+#include "memory/allocation.hpp"
 #include "runtime/handles.hpp"
 
 class ClassFileStream;
--- a/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -34,6 +34,18 @@
 #include "runtime/arguments.hpp"
 #include "utilities/ostream.hpp"
 
+SharedPathsMiscInfo::SharedPathsMiscInfo() {
+  _buf_size = INITIAL_BUF_SIZE;
+  _cur_ptr = _buf_start = NEW_C_HEAP_ARRAY(char, _buf_size, mtClass);
+  _allocated = true;
+}
+
+SharedPathsMiscInfo::~SharedPathsMiscInfo() {
+  if (_allocated) {
+    FREE_C_HEAP_ARRAY(char, _buf_start);
+  }
+}
+
 void SharedPathsMiscInfo::add_path(const char* path, int type) {
   log_info(class, path)("type=%s ", type_name(type));
   ClassLoader::trace_class_path("add misc shared path ", path);
--- a/src/hotspot/share/classfile/sharedPathsMiscInfo.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/classfile/sharedPathsMiscInfo.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -74,11 +74,7 @@
     INITIAL_BUF_SIZE = 128
   };
   // This constructor is used when creating the misc information (during dump)
-  SharedPathsMiscInfo() {
-    _buf_size = INITIAL_BUF_SIZE;
-    _cur_ptr = _buf_start = NEW_C_HEAP_ARRAY(char, _buf_size, mtClass);
-    _allocated = true;
-  }
+  SharedPathsMiscInfo();
   // This constructor is used when validating the misc info (during run time)
   SharedPathsMiscInfo(char *buff, int size) {
     _cur_ptr = _buf_start = buff;
@@ -86,11 +82,8 @@
     _buf_size = size;
     _allocated = false;
   }
-  ~SharedPathsMiscInfo() {
-    if (_allocated) {
-      FREE_C_HEAP_ARRAY(char, _buf_start);
-    }
-  }
+  ~SharedPathsMiscInfo();
+
   int get_used_bytes() {
     return _cur_ptr - _buf_start;
   }
--- a/src/hotspot/share/classfile/stringTable.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/classfile/stringTable.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -25,7 +25,7 @@
 #ifndef SHARE_VM_CLASSFILE_STRINGTABLE_HPP
 #define SHARE_VM_CLASSFILE_STRINGTABLE_HPP
 
-#include "memory/allocation.inline.hpp"
+#include "memory/allocation.hpp"
 #include "utilities/hashtable.hpp"
 
 template <class T, class N> class CompactHashtable;
--- a/src/hotspot/share/classfile/symbolTable.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/classfile/symbolTable.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -25,7 +25,7 @@
 #ifndef SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP
 #define SHARE_VM_CLASSFILE_SYMBOLTABLE_HPP
 
-#include "memory/allocation.inline.hpp"
+#include "memory/allocation.hpp"
 #include "oops/symbol.hpp"
 #include "utilities/hashtable.hpp"
 
--- a/src/hotspot/share/compiler/compileTask.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/compiler/compileTask.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -25,10 +25,10 @@
 #ifndef SHARE_VM_COMPILER_COMPILETASK_HPP
 #define SHARE_VM_COMPILER_COMPILETASK_HPP
 
+#include "ci/ciMethod.hpp"
 #include "code/nmethod.hpp"
-#include "ci/ciMethod.hpp"
 #include "compiler/compileLog.hpp"
-#include "memory/allocation.inline.hpp"
+#include "memory/allocation.hpp"
 #include "utilities/xmlstream.hpp"
 
 // CompileTask
--- a/src/hotspot/share/compiler/methodMatcher.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/compiler/methodMatcher.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -25,7 +25,7 @@
 #ifndef SHARE_VM_COMPILER_METHODMATCHER_HPP
 #define SHARE_VM_COMPILER_METHODMATCHER_HPP
 
-#include "memory/allocation.inline.hpp"
+#include "memory/allocation.hpp"
 #include "runtime/handles.inline.hpp"
 #include "memory/resourceArea.hpp"
 
--- a/src/hotspot/share/compiler/oopMap.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/compiler/oopMap.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -28,6 +28,7 @@
 #include "code/compressedStream.hpp"
 #include "code/vmreg.hpp"
 #include "memory/allocation.hpp"
+#include "oops/oopsHierarchy.hpp"
 #include "utilities/growableArray.hpp"
 
 // Interface for generating the frame map for compiled code.  A frame map
@@ -42,6 +43,7 @@
 class frame;
 class RegisterMap;
 class DerivedPointerEntry;
+class OopClosure;
 
 class OopMapValue: public StackObj {
   friend class VMStructs;
--- a/src/hotspot/share/gc/cms/allocationStats.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/cms/allocationStats.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -30,3 +30,20 @@
 // Technically this should be derived from machine speed, and
 // ideally it would be dynamically adjusted.
 float AllocationStats::_threshold = ((float)CMS_SweepTimerThresholdMillis)/1000;
+
+void AllocationStats::initialize(bool split_birth)   {
+  AdaptivePaddedAverage* dummy =
+    new (&_demand_rate_estimate) AdaptivePaddedAverage(CMS_FLSWeight,
+                                                       CMS_FLSPadding);
+  _desired = 0;
+  _coal_desired = 0;
+  _surplus = 0;
+  _bfr_surp = 0;
+  _prev_sweep = 0;
+  _before_sweep = 0;
+  _coal_births = 0;
+  _coal_deaths = 0;
+  _split_births = (split_birth ? 1 : 0);
+  _split_deaths = 0;
+  _returned_bytes = 0;
+}
--- a/src/hotspot/share/gc/cms/allocationStats.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/cms/allocationStats.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -64,22 +64,7 @@
   ssize_t     _split_deaths;     // loss from splitting
   size_t      _returned_bytes;   // number of bytes returned to list.
  public:
-  void initialize(bool split_birth = false) {
-    AdaptivePaddedAverage* dummy =
-      new (&_demand_rate_estimate) AdaptivePaddedAverage(CMS_FLSWeight,
-                                                         CMS_FLSPadding);
-    _desired = 0;
-    _coal_desired = 0;
-    _surplus = 0;
-    _bfr_surp = 0;
-    _prev_sweep = 0;
-    _before_sweep = 0;
-    _coal_births = 0;
-    _coal_deaths = 0;
-    _split_births = (split_birth ? 1 : 0);
-    _split_deaths = 0;
-    _returned_bytes = 0;
-  }
+  void initialize(bool split_birth = false);
 
   AllocationStats() {
     initialize();
--- a/src/hotspot/share/gc/cms/gSpaceCounters.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/cms/gSpaceCounters.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "gc/cms/gSpaceCounters.hpp"
 #include "gc/shared/generation.hpp"
+#include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "utilities/macros.hpp"
 
@@ -71,3 +72,7 @@
                                      _gen->capacity(), CHECK);
   }
 }
+
+GSpaceCounters::~GSpaceCounters() {
+  if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space);
+}
--- a/src/hotspot/share/gc/cms/gSpaceCounters.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/cms/gSpaceCounters.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -52,9 +52,7 @@
   GSpaceCounters(const char* name, int ordinal, size_t max_size, Generation* g,
                  GenerationCounters* gc, bool sampled=true);
 
-  ~GSpaceCounters() {
-    if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space);
-  }
+  ~GSpaceCounters();
 
   inline void update_capacity() {
     _capacity->set_value(_gen->capacity());
--- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -26,6 +26,7 @@
 #include "gc/g1/g1ConcurrentRefine.hpp"
 #include "gc/g1/g1ConcurrentRefineThread.hpp"
 #include "logging/log.hpp"
+#include "memory/allocation.inline.hpp"
 #include "runtime/java.hpp"
 #include "runtime/thread.hpp"
 #include "utilities/debug.hpp"
--- a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -26,6 +26,7 @@
 #define SHARE_GC_G1_G1FULLGCCOMPACTIONPOINT_HPP
 
 #include "memory/allocation.hpp"
+#include "oops/oopsHierarchy.hpp"
 #include "utilities/growableArray.hpp"
 
 class HeapRegion;
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -32,6 +32,7 @@
 #include "gc/g1/g1StringDedup.hpp"
 #include "gc/shared/gcTrace.hpp"
 #include "gc/shared/taskqueue.inline.hpp"
+#include "memory/allocation.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/prefetch.inline.hpp"
 
@@ -390,3 +391,21 @@
   }
 }
 
+G1ParScanThreadStateSet::G1ParScanThreadStateSet(G1CollectedHeap* g1h, uint n_workers, size_t young_cset_length) :
+    _g1h(g1h),
+    _states(NEW_C_HEAP_ARRAY(G1ParScanThreadState*, n_workers, mtGC)),
+    _surviving_young_words_total(NEW_C_HEAP_ARRAY(size_t, young_cset_length, mtGC)),
+    _young_cset_length(young_cset_length),
+    _n_workers(n_workers),
+    _flushed(false) {
+  for (uint i = 0; i < n_workers; ++i) {
+    _states[i] = NULL;
+  }
+  memset(_surviving_young_words_total, 0, young_cset_length * sizeof(size_t));
+}
+
+G1ParScanThreadStateSet::~G1ParScanThreadStateSet() {
+  assert(_flushed, "thread local state from the per thread states should have been flushed");
+  FREE_C_HEAP_ARRAY(G1ParScanThreadState*, _states);
+  FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_total);
+}
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -204,24 +204,8 @@
   bool _flushed;
 
  public:
-  G1ParScanThreadStateSet(G1CollectedHeap* g1h, uint n_workers, size_t young_cset_length) :
-      _g1h(g1h),
-      _states(NEW_C_HEAP_ARRAY(G1ParScanThreadState*, n_workers, mtGC)),
-      _surviving_young_words_total(NEW_C_HEAP_ARRAY(size_t, young_cset_length, mtGC)),
-      _young_cset_length(young_cset_length),
-      _n_workers(n_workers),
-      _flushed(false) {
-    for (uint i = 0; i < n_workers; ++i) {
-      _states[i] = NULL;
-    }
-    memset(_surviving_young_words_total, 0, young_cset_length * sizeof(size_t));
-  }
-
-  ~G1ParScanThreadStateSet() {
-    assert(_flushed, "thread local state from the per thread states should have been flushed");
-    FREE_C_HEAP_ARRAY(G1ParScanThreadState*, _states);
-    FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_total);
-  }
+  G1ParScanThreadStateSet(G1CollectedHeap* g1h, uint n_workers, size_t young_cset_length);
+  ~G1ParScanThreadStateSet();
 
   void flush();
 
--- a/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -29,6 +29,7 @@
 #include "gc/parallel/psScavenge.hpp"
 #include "gc/shared/collectorPolicy.hpp"
 #include "gc/shared/gcCause.hpp"
+#include "gc/shared/gcUtil.inline.hpp"
 #include "gc/shared/gcPolicyCounters.hpp"
 #include "logging/log.hpp"
 #include "runtime/timer.hpp"
--- a/src/hotspot/share/gc/parallel/psGenerationCounters.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/parallel/psGenerationCounters.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -25,9 +25,9 @@
 
 #include "precompiled.hpp"
 #include "gc/parallel/psGenerationCounters.hpp"
+#include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
 
-
 PSGenerationCounters::PSGenerationCounters(const char* name,
                                        int ordinal, int spaces,
                                        size_t min_capacity,
--- a/src/hotspot/share/gc/parallel/spaceCounters.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/parallel/spaceCounters.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc/parallel/spaceCounters.hpp"
+#include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "utilities/macros.hpp"
 
@@ -63,3 +64,7 @@
                                      _object_space->capacity_in_bytes(), CHECK);
   }
 }
+
+SpaceCounters::~SpaceCounters() {
+  if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space);
+}
--- a/src/hotspot/share/gc/parallel/spaceCounters.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/parallel/spaceCounters.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -53,9 +53,7 @@
   SpaceCounters(const char* name, int ordinal, size_t max_size,
                 MutableSpace* m, GenerationCounters* gc);
 
-  ~SpaceCounters() {
-    if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space);
-  }
+  ~SpaceCounters();
 
   inline void update_capacity() {
     _capacity->set_value(_object_space->capacity_in_bytes());
--- a/src/hotspot/share/gc/serial/cSpaceCounters.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/serial/cSpaceCounters.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc/serial/cSpaceCounters.hpp"
+#include "memory/allocation.inline.hpp"
 #include "memory/metaspace.hpp"
 #include "memory/resourceArea.hpp"
 
@@ -64,6 +65,10 @@
   }
 }
 
+CSpaceCounters::~CSpaceCounters() {
+    if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space);
+}
+
 void CSpaceCounters::update_capacity() {
   _capacity->set_value(_space->capacity());
 }
--- a/src/hotspot/share/gc/serial/cSpaceCounters.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/serial/cSpaceCounters.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -52,9 +52,7 @@
   CSpaceCounters(const char* name, int ordinal, size_t max_size,
                  ContiguousSpace* s, GenerationCounters* gc);
 
-  ~CSpaceCounters() {
-      if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space);
-  }
+  ~CSpaceCounters();
 
   virtual void update_capacity();
   virtual void update_used();
--- a/src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -26,6 +26,7 @@
 #include "gc/shared/adaptiveSizePolicy.hpp"
 #include "gc/shared/collectorPolicy.hpp"
 #include "gc/shared/gcCause.hpp"
+#include "gc/shared/gcUtil.inline.hpp"
 #include "gc/shared/workgroup.hpp"
 #include "logging/log.hpp"
 #include "runtime/timer.hpp"
--- a/src/hotspot/share/gc/shared/collectorCounters.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/shared/collectorCounters.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc/shared/collectorCounters.hpp"
+#include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/os.hpp"
 
--- a/src/hotspot/share/gc/shared/gcStats.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/shared/gcStats.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -24,8 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc/shared/gcStats.hpp"
-#include "gc/shared/gcUtil.hpp"
-#include "memory/allocation.inline.hpp"
+#include "gc/shared/gcUtil.inline.hpp"
 
 GCStats::GCStats() {
     _avg_promoted       = new AdaptivePaddedNoZeroDevAverage(
--- a/src/hotspot/share/gc/shared/gcUtil.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/shared/gcUtil.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -146,7 +146,7 @@
   // Placement support
   void* operator new(size_t ignored, void* p) throw() { return p; }
   // Allocator
-  void* operator new(size_t size) throw() { return CHeapObj<mtGC>::operator new(size); }
+  void* operator new(size_t size) throw();
 
   // Accessor
   float padded_average() const         { return _padded_avg; }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/gcUtil.inline.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2002, 2015, 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_VM_GC_SHARED_GCUTIL_INLINE_HPP
+#define SHARE_VM_GC_SHARED_GCUTIL_INLINE_HPP
+
+#include "gc/shared/gcUtil.hpp"
+#include "memory/allocation.inline.hpp"
+
+inline void* AdaptivePaddedAverage::operator new(size_t size) throw() {
+  return CHeapObj<mtGC>::operator new(size);
+}
+
+#endif // SHARE_VM_GC_SHARED_GCUTIL_INLINE_HPP
--- a/src/hotspot/share/gc/shared/generationCounters.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/shared/generationCounters.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc/shared/generationCounters.hpp"
+#include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
 
 void GenerationCounters::initialize(const char* name, int ordinal, int spaces,
--- a/src/hotspot/share/gc/shared/hSpaceCounters.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/shared/hSpaceCounters.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -24,7 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc/shared/hSpaceCounters.hpp"
-#include "memory/allocation.hpp"
+#include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/perfData.hpp"
 
--- a/src/hotspot/share/gc/shared/taskqueue.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/gc/shared/taskqueue.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -26,6 +26,8 @@
 #define SHARE_VM_GC_SHARED_TASKQUEUE_HPP
 
 #include "memory/allocation.hpp"
+#include "oops/oopsHierarchy.hpp"
+#include "utilities/ostream.hpp"
 #include "utilities/stack.hpp"
 
 // Simple TaskQueue stats that are collected by default in debug builds.
--- a/src/hotspot/share/memory/resourceArea.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/memory/resourceArea.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -24,7 +24,7 @@
 
 #include "precompiled.hpp"
 #include "memory/allocation.inline.hpp"
-#include "memory/resourceArea.hpp"
+#include "memory/resourceArea.inline.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/thread.inline.hpp"
 #include "services/memTracker.hpp"
--- a/src/hotspot/share/memory/resourceArea.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/memory/resourceArea.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -57,18 +57,7 @@
     debug_only(_nesting = 0;);
   }
 
-  char* allocate_bytes(size_t size, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
-#ifdef ASSERT
-    if (_nesting < 1 && !_warned++)
-      fatal("memory leak: allocating without ResourceMark");
-    if (UseMallocOnly) {
-      // use malloc, but save pointer in res. area for later freeing
-      char** save = (char**)internal_malloc_4(sizeof(char*));
-      return (*save = (char*)os::malloc(size, mtThread, CURRENT_PC));
-    }
-#endif
-    return (char*)Amalloc(size, alloc_failmode);
-  }
+  char* allocate_bytes(size_t size, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM);
 
   // Bias this resource area to specific memory type
   // (by default, ResourceArea is tagged as mtThread, per-thread general purpose storage)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/memory/resourceArea.inline.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1997, 2017, 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_VM_MEMORY_RESOURCEAREA_INLINE_HPP
+#define SHARE_VM_MEMORY_RESOURCEAREA_INLINE_HPP
+
+#include "memory/resourceArea.hpp"
+
+inline char* ResourceArea::allocate_bytes(size_t size, AllocFailType alloc_failmode) {
+#ifdef ASSERT
+  if (_nesting < 1 && !_warned++)
+    fatal("memory leak: allocating without ResourceMark");
+  if (UseMallocOnly) {
+    // use malloc, but save pointer in res. area for later freeing
+    char** save = (char**)internal_malloc_4(sizeof(char*));
+    return (*save = (char*)os::malloc(size, mtThread, CURRENT_PC));
+  }
+#endif
+  return (char*)Amalloc(size, alloc_failmode);
+}
+
+#endif // SHARE_VM_MEMORY_RESOURCEAREA_INLINE_HPP
--- a/src/hotspot/share/memory/universe.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/memory/universe.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -856,7 +856,7 @@
       || use_large_pages, "Wrong alignment to use large pages");
 
   // Now create the space.
-  ReservedHeapSpace total_rs(total_reserved, alignment, use_large_pages);
+  ReservedHeapSpace total_rs(total_reserved, alignment, use_large_pages, AllocateHeapAt);
 
   if (total_rs.is_reserved()) {
     assert((total_reserved == total_rs.size()) && ((uintptr_t)total_rs.base() % alignment == 0),
@@ -870,6 +870,9 @@
       Universe::set_narrow_oop_base((address)total_rs.compressed_oop_base());
     }
 
+    if (AllocateHeapAt != NULL) {
+      log_info(gc,heap)("Successfully allocated Java heap at location %s", AllocateHeapAt);
+    }
     return total_rs;
   }
 
--- a/src/hotspot/share/memory/virtualspace.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/memory/virtualspace.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -35,10 +35,10 @@
 
 // Dummy constructor
 ReservedSpace::ReservedSpace() : _base(NULL), _size(0), _noaccess_prefix(0),
-    _alignment(0), _special(false), _executable(false) {
+    _alignment(0), _special(false), _executable(false), _fd_for_heap(-1) {
 }
 
-ReservedSpace::ReservedSpace(size_t size, size_t preferred_page_size) {
+ReservedSpace::ReservedSpace(size_t size, size_t preferred_page_size) : _fd_for_heap(-1) {
   bool has_preferred_page_size = preferred_page_size != 0;
   // Want to use large pages where possible and pad with small pages.
   size_t page_size = has_preferred_page_size ? preferred_page_size : os::page_size_for_region_unaligned(size, 1);
@@ -59,19 +59,30 @@
 
 ReservedSpace::ReservedSpace(size_t size, size_t alignment,
                              bool large,
-                             char* requested_address) {
+                             char* requested_address) : _fd_for_heap(-1) {
   initialize(size, alignment, large, requested_address, false);
 }
 
 ReservedSpace::ReservedSpace(size_t size, size_t alignment,
                              bool large,
-                             bool executable) {
+                             bool executable) : _fd_for_heap(-1) {
   initialize(size, alignment, large, NULL, executable);
 }
 
+// Helper method
+static void unmap_or_release_memory(char* base, size_t size, bool is_file_mapped) {
+  if (is_file_mapped) {
+    if (!os::unmap_memory(base, size)) {
+      fatal("os::unmap_memory failed");
+    }
+  } else if (!os::release_memory(base, size)) {
+    fatal("os::release_memory failed");
+  }
+}
+
 // Helper method.
 static bool failed_to_reserve_as_requested(char* base, char* requested_address,
-                                           const size_t size, bool special)
+                                           const size_t size, bool special, bool is_file_mapped = false)
 {
   if (base == requested_address || requested_address == NULL)
     return false; // did not fail
@@ -87,9 +98,7 @@
         fatal("os::release_memory_special failed");
       }
     } else {
-      if (!os::release_memory(base, size)) {
-        fatal("os::release_memory failed");
-      }
+      unmap_or_release_memory(base, size, is_file_mapped);
     }
   }
   return true;
@@ -120,7 +129,18 @@
 
   // If OS doesn't support demand paging for large page memory, we need
   // to use reserve_memory_special() to reserve and pin the entire region.
+  // If there is a backing file directory for this space then whether
+  // large pages are allocated is up to the filesystem of the backing file.
+  // So we ignore the UseLargePages flag in this case.
   bool special = large && !os::can_commit_large_page_memory();
+  if (special && _fd_for_heap != -1) {
+    special = false;
+    if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) ||
+      !FLAG_IS_DEFAULT(LargePageSizeInBytes))) {
+      log_debug(gc, heap)("Ignoring UseLargePages since large page support is up to the file system of the backing file for Java heap");
+    }
+  }
+
   char* base = NULL;
 
   if (special) {
@@ -157,13 +177,13 @@
     // important.  If available space is not detected, return NULL.
 
     if (requested_address != 0) {
-      base = os::attempt_reserve_memory_at(size, requested_address);
-      if (failed_to_reserve_as_requested(base, requested_address, size, false)) {
+      base = os::attempt_reserve_memory_at(size, requested_address, _fd_for_heap);
+      if (failed_to_reserve_as_requested(base, requested_address, size, false, _fd_for_heap != -1)) {
         // OS ignored requested address. Try different address.
         base = NULL;
       }
     } else {
-      base = os::reserve_memory(size, NULL, alignment);
+      base = os::reserve_memory(size, NULL, alignment, _fd_for_heap);
     }
 
     if (base == NULL) return;
@@ -171,13 +191,14 @@
     // Check alignment constraints
     if ((((size_t)base) & (alignment - 1)) != 0) {
       // Base not aligned, retry
-      if (!os::release_memory(base, size)) fatal("os::release_memory failed");
+      unmap_or_release_memory(base, size, _fd_for_heap != -1 /*is_file_mapped*/);
+
       // Make sure that size is aligned
       size = align_up(size, alignment);
-      base = os::reserve_memory_aligned(size, alignment);
+      base = os::reserve_memory_aligned(size, alignment, _fd_for_heap);
 
       if (requested_address != 0 &&
-          failed_to_reserve_as_requested(base, requested_address, size, false)) {
+          failed_to_reserve_as_requested(base, requested_address, size, false, _fd_for_heap != -1)) {
         // As a result of the alignment constraints, the allocated base differs
         // from the requested address. Return back to the caller who can
         // take remedial action (like try again without a requested address).
@@ -190,6 +211,10 @@
   _base = base;
   _size = size;
   _alignment = alignment;
+  // If heap is reserved with a backing file, the entire space has been committed. So set the _special flag to true
+  if (_fd_for_heap != -1) {
+    _special = true;
+  }
 }
 
 
@@ -252,7 +277,11 @@
     char *real_base = _base - _noaccess_prefix;
     const size_t real_size = _size + _noaccess_prefix;
     if (special()) {
-      os::release_memory_special(real_base, real_size);
+      if (_fd_for_heap != -1) {
+        os::unmap_memory(real_base, real_size);
+      } else {
+        os::release_memory_special(real_base, real_size);
+      }
     } else{
       os::release_memory(real_base, real_size);
     }
@@ -313,7 +342,17 @@
 
   // If OS doesn't support demand paging for large page memory, we need
   // to use reserve_memory_special() to reserve and pin the entire region.
+  // If there is a backing file directory for this space then whether
+  // large pages are allocated is up to the filesystem of the backing file.
+  // So we ignore the UseLargePages flag in this case.
   bool special = large && !os::can_commit_large_page_memory();
+  if (special && _fd_for_heap != -1) {
+    special = false;
+    if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) ||
+                          !FLAG_IS_DEFAULT(LargePageSizeInBytes))) {
+      log_debug(gc, heap)("Cannot allocate large pages for Java Heap when AllocateHeapAt option is set.");
+    }
+  }
   char* base = NULL;
 
   log_trace(gc, heap, coops)("Trying to allocate at address " PTR_FORMAT
@@ -350,9 +389,9 @@
     // important.  If available space is not detected, return NULL.
 
     if (requested_address != 0) {
-      base = os::attempt_reserve_memory_at(size, requested_address);
+      base = os::attempt_reserve_memory_at(size, requested_address, _fd_for_heap);
     } else {
-      base = os::reserve_memory(size, NULL, alignment);
+      base = os::reserve_memory(size, NULL, alignment, _fd_for_heap);
     }
   }
   if (base == NULL) { return; }
@@ -362,6 +401,11 @@
   _size = size;
   _alignment = alignment;
 
+  // If heap is reserved with a backing file, the entire space has been committed. So set the _special flag to true
+  if (_fd_for_heap != -1) {
+    _special = true;
+  }
+
   // Check alignment constraints
   if ((((size_t)base) & (alignment - 1)) != 0) {
     // Base not aligned, retry.
@@ -556,12 +600,20 @@
   }
 }
 
-ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment, bool large) : ReservedSpace() {
+ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment, bool large, const char* heap_allocation_directory) : ReservedSpace() {
 
   if (size == 0) {
     return;
   }
 
+  if (heap_allocation_directory != NULL) {
+    _fd_for_heap = os::create_file_for_heap(heap_allocation_directory);
+    if (_fd_for_heap == -1) {
+      vm_exit_during_initialization(
+        err_msg("Could not create file for Heap at location %s", heap_allocation_directory));
+    }
+  }
+
   // Heap size should be aligned to alignment, too.
   guarantee(is_aligned(size, alignment), "set by caller");
 
@@ -585,6 +637,10 @@
   if (base() != NULL) {
     MemTracker::record_virtual_memory_type((address)base(), mtJavaHeap);
   }
+
+  if (_fd_for_heap != -1) {
+    os::close(_fd_for_heap);
+  }
 }
 
 // Reserve space for code segment.  Same as Java heap only we mark this as
--- a/src/hotspot/share/memory/virtualspace.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/memory/virtualspace.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -37,6 +37,7 @@
   size_t _noaccess_prefix;
   size_t _alignment;
   bool   _special;
+  int    _fd_for_heap;
  private:
   bool   _executable;
 
@@ -115,7 +116,9 @@
   void establish_noaccess_prefix();
  public:
   // Constructor. Tries to find a heap that is good for compressed oops.
-  ReservedHeapSpace(size_t size, size_t forced_base_alignment, bool large);
+  // heap_allocation_directory is the path to the backing memory for Java heap. When set, Java heap will be allocated
+  // on the device which is managed by the file system where the directory resides.
+  ReservedHeapSpace(size_t size, size_t forced_base_alignment, bool large, const char* heap_allocation_directory = NULL);
   // Returns the base to be used for compression, i.e. so that null can be
   // encoded safely and implicit null checks can work.
   char *compressed_oop_base() { return _base - _noaccess_prefix; }
--- a/src/hotspot/share/oops/array.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/oops/array.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -26,7 +26,6 @@
 #define SHARE_VM_OOPS_ARRAY_HPP
 
 #include "memory/allocation.hpp"
-#include "memory/allocation.inline.hpp"
 #include "memory/metaspace.hpp"
 #include "runtime/orderAccess.hpp"
 #include "utilities/align.hpp"
--- a/src/hotspot/share/oops/constantPool.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/oops/constantPool.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -31,6 +31,7 @@
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "interpreter/linkResolver.hpp"
+#include "memory/allocation.inline.hpp"
 #include "memory/heapInspection.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/metaspaceClosure.hpp"
@@ -2300,3 +2301,11 @@
   }
   return NULL;
 }
+
+void SymbolHashMap::initialize_table(int table_size) {
+  _table_size = table_size;
+  _buckets = NEW_C_HEAP_ARRAY(SymbolHashMapBucket, table_size, mtSymbol);
+  for (int index = 0; index < table_size; index++) {
+    _buckets[index].clear();
+  }
+}
--- a/src/hotspot/share/oops/constantPool.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/oops/constantPool.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -982,13 +982,7 @@
   int                   _table_size;
   SymbolHashMapBucket*  _buckets;
 
-  void initialize_table(int table_size) {
-    _table_size = table_size;
-    _buckets = NEW_C_HEAP_ARRAY(SymbolHashMapBucket, table_size, mtSymbol);
-    for (int index = 0; index < table_size; index++) {
-      _buckets[index].clear();
-    }
-  }
+  void initialize_table(int table_size);
 
  public:
 
--- a/src/hotspot/share/oops/generateOopMap.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/oops/generateOopMap.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -27,6 +27,7 @@
 #include "interpreter/bytecodeStream.hpp"
 #include "logging/log.hpp"
 #include "logging/logStream.hpp"
+#include "memory/allocation.inline.hpp"
 #include "oops/generateOopMap.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/symbol.hpp"
@@ -217,6 +218,12 @@
 int RetTable::_init_nof_entries = 10;
 int RetTableEntry::_init_nof_jsrs = 5;
 
+RetTableEntry::RetTableEntry(int target, RetTableEntry *next) {
+  _target_bci = target;
+  _jsrs = new GrowableArray<intptr_t>(_init_nof_jsrs);
+  _next = next;
+}
+
 void RetTableEntry::add_delta(int bci, int delta) {
   if (_target_bci > bci) _target_bci += delta;
 
--- a/src/hotspot/share/oops/generateOopMap.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/oops/generateOopMap.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -26,7 +26,7 @@
 #define SHARE_VM_OOPS_GENERATEOOPMAP_HPP
 
 #include "interpreter/bytecodeStream.hpp"
-#include "memory/allocation.inline.hpp"
+#include "memory/allocation.hpp"
 #include "memory/universe.inline.hpp"
 #include "oops/method.hpp"
 #include "oops/oopsHierarchy.hpp"
@@ -57,7 +57,7 @@
   GrowableArray<intptr_t> * _jsrs;                     // List of return addresses  (bytecode index)
   RetTableEntry *_next;                           // Link to next entry
  public:
-   RetTableEntry(int target, RetTableEntry *next)  { _target_bci=target; _jsrs = new GrowableArray<intptr_t>(_init_nof_jsrs); _next = next;  }
+   RetTableEntry(int target, RetTableEntry *next);
 
   // Query
   int target_bci() const                      { return _target_bci; }
--- a/src/hotspot/share/opto/reg_split.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/opto/reg_split.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -25,7 +25,7 @@
 #include "precompiled.hpp"
 #include "libadt/vectset.hpp"
 #include "memory/allocation.inline.hpp"
-#include "memory/resourceArea.hpp"
+#include "memory/resourceArea.inline.hpp"
 #include "opto/addnode.hpp"
 #include "opto/c2compiler.hpp"
 #include "opto/callnode.hpp"
--- a/src/hotspot/share/precompiled/precompiled.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/precompiled/precompiled.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -131,7 +131,6 @@
 # include "jvmtifiles/jvmti.h"
 # include "logging/log.hpp"
 # include "memory/allocation.hpp"
-# include "memory/allocation.inline.hpp"
 # include "memory/arena.hpp"
 # include "memory/heap.hpp"
 # include "memory/iterator.hpp"
--- a/src/hotspot/share/prims/jvmtiEnvThreadState.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/prims/jvmtiEnvThreadState.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -27,7 +27,6 @@
 
 #include "jvmtifiles/jvmti.h"
 #include "memory/allocation.hpp"
-#include "memory/allocation.inline.hpp"
 #include "oops/instanceKlass.hpp"
 #include "prims/jvmtiEventController.hpp"
 #include "utilities/globalDefinitions.hpp"
--- a/src/hotspot/share/prims/jvmtiEventController.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/prims/jvmtiEventController.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -27,7 +27,6 @@
 
 #include "jvmtifiles/jvmti.h"
 #include "memory/allocation.hpp"
-#include "memory/allocation.inline.hpp"
 #include "utilities/globalDefinitions.hpp"
 
 // forward declaration
--- a/src/hotspot/share/prims/jvmtiThreadState.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/prims/jvmtiThreadState.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -27,7 +27,6 @@
 
 #include "jvmtifiles/jvmti.h"
 #include "memory/allocation.hpp"
-#include "memory/allocation.inline.hpp"
 #include "prims/jvmtiEventController.hpp"
 #include "runtime/thread.hpp"
 #include "utilities/growableArray.hpp"
--- a/src/hotspot/share/prims/methodHandles.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/prims/methodHandles.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -1029,6 +1029,26 @@
   }
 }
 
+void MethodHandles::trace_method_handle_interpreter_entry(MacroAssembler* _masm, vmIntrinsics::ID iid) {
+  if (TraceMethodHandles) {
+    const char* name = vmIntrinsics::name_at(iid);
+    if (*name == '_')  name += 1;
+    const size_t len = strlen(name) + 50;
+    char* qname = NEW_C_HEAP_ARRAY(char, len, mtInternal);
+    const char* suffix = "";
+    if (is_signature_polymorphic(iid)) {
+      if (is_signature_polymorphic_static(iid))
+        suffix = "/static";
+      else
+        suffix = "/private";
+    }
+    jio_snprintf(qname, len, "MethodHandle::interpreter_entry::%s%s", name, suffix);
+    trace_method_handle(_masm, qname);
+    // Note:  Don't free the allocated char array because it's used
+    // during runtime.
+  }
+}
+
 //
 // Here are the native methods in java.lang.invoke.MethodHandleNatives
 // They are the private interface between this JVM and the HotSpot-specific
--- a/src/hotspot/share/prims/methodHandles.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/prims/methodHandles.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -195,25 +195,7 @@
 
   // Tracing
   static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN;
-  static void trace_method_handle_interpreter_entry(MacroAssembler* _masm, vmIntrinsics::ID iid) {
-    if (TraceMethodHandles) {
-      const char* name = vmIntrinsics::name_at(iid);
-      if (*name == '_')  name += 1;
-      const size_t len = strlen(name) + 50;
-      char* qname = NEW_C_HEAP_ARRAY(char, len, mtInternal);
-      const char* suffix = "";
-      if (is_signature_polymorphic(iid)) {
-        if (is_signature_polymorphic_static(iid))
-          suffix = "/static";
-        else
-          suffix = "/private";
-      }
-      jio_snprintf(qname, len, "MethodHandle::interpreter_entry::%s%s", name, suffix);
-      trace_method_handle(_masm, qname);
-      // Note:  Don't free the allocated char array because it's used
-      // during runtime.
-    }
-  }
+  static void trace_method_handle_interpreter_entry(MacroAssembler* _masm, vmIntrinsics::ID iid);
 };
 
 //------------------------------------------------------------------------------
--- a/src/hotspot/share/runtime/arguments.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/runtime/arguments.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -114,6 +114,108 @@
 
 char* Arguments::_ext_dirs = NULL;
 
+bool PathString::set_value(const char *value) {
+  if (_value != NULL) {
+    FreeHeap(_value);
+  }
+  _value = AllocateHeap(strlen(value)+1, mtArguments);
+  assert(_value != NULL, "Unable to allocate space for new path value");
+  if (_value != NULL) {
+    strcpy(_value, value);
+  } else {
+    // not able to allocate
+    return false;
+  }
+  return true;
+}
+
+void PathString::append_value(const char *value) {
+  char *sp;
+  size_t len = 0;
+  if (value != NULL) {
+    len = strlen(value);
+    if (_value != NULL) {
+      len += strlen(_value);
+    }
+    sp = AllocateHeap(len+2, mtArguments);
+    assert(sp != NULL, "Unable to allocate space for new append path value");
+    if (sp != NULL) {
+      if (_value != NULL) {
+        strcpy(sp, _value);
+        strcat(sp, os::path_separator());
+        strcat(sp, value);
+        FreeHeap(_value);
+      } else {
+        strcpy(sp, value);
+      }
+      _value = sp;
+    }
+  }
+}
+
+PathString::PathString(const char* value) {
+  if (value == NULL) {
+    _value = NULL;
+  } else {
+    _value = AllocateHeap(strlen(value)+1, mtArguments);
+    strcpy(_value, value);
+  }
+}
+
+PathString::~PathString() {
+  if (_value != NULL) {
+    FreeHeap(_value);
+    _value = NULL;
+  }
+}
+
+ModulePatchPath::ModulePatchPath(const char* module_name, const char* path) {
+  assert(module_name != NULL && path != NULL, "Invalid module name or path value");
+  size_t len = strlen(module_name) + 1;
+  _module_name = AllocateHeap(len, mtInternal);
+  strncpy(_module_name, module_name, len); // copy the trailing null
+  _path =  new PathString(path);
+}
+
+ModulePatchPath::~ModulePatchPath() {
+  if (_module_name != NULL) {
+    FreeHeap(_module_name);
+    _module_name = NULL;
+  }
+  if (_path != NULL) {
+    delete _path;
+    _path = NULL;
+  }
+}
+
+SystemProperty::SystemProperty(const char* key, const char* value, bool writeable, bool internal) : PathString(value) {
+  if (key == NULL) {
+    _key = NULL;
+  } else {
+    _key = AllocateHeap(strlen(key)+1, mtArguments);
+    strcpy(_key, key);
+  }
+  _next = NULL;
+  _internal = internal;
+  _writeable = writeable;
+}
+
+AgentLibrary::AgentLibrary(const char* name, const char* options, bool is_absolute_path, void* os_lib) {
+  _name = AllocateHeap(strlen(name)+1, mtArguments);
+  strcpy(_name, name);
+  if (options == NULL) {
+    _options = NULL;
+  } else {
+    _options = AllocateHeap(strlen(options)+1, mtArguments);
+    strcpy(_options, options);
+  }
+  _is_absolute_path = is_absolute_path;
+  _os_lib = os_lib;
+  _next = NULL;
+  _state = agent_invalid;
+  _is_static_lib = false;
+}
+
 // Check if head of 'option' matches 'name', and sets 'tail' to the remaining
 // part of the option string.
 static bool match_option(const JavaVMOption *option, const char* name,
@@ -180,6 +282,23 @@
 #define UPGRADE_PATH "upgrade.path"
 #define UPGRADE_PATH_LEN 12
 
+void Arguments::add_init_library(const char* name, char* options) {
+  _libraryList.add(new AgentLibrary(name, options, false, NULL));
+}
+
+void Arguments::add_init_agent(const char* name, char* options, bool absolute_path) {
+  _agentList.add(new AgentLibrary(name, options, absolute_path, NULL));
+}
+
+// Late-binding agents not started via arguments
+void Arguments::add_loaded_agent(AgentLibrary *agentLib) {
+  _agentList.add(agentLib);
+}
+
+void Arguments::add_loaded_agent(const char* name, char* options, bool absolute_path, void* os_lib) {
+  _agentList.add(new AgentLibrary(name, options, absolute_path, os_lib));
+}
+
 // Return TRUE if option matches 'property', or 'property=', or 'property.'.
 static bool matches_property_suffix(const char* option, const char* property, size_t len) {
   return ((strncmp(option, property, len) == 0) &&
@@ -2223,6 +2342,11 @@
     LoopStripMiningIterShortLoop = LoopStripMiningIter / 10;
   }
 #endif
+  if (!FLAG_IS_DEFAULT(AllocateHeapAt)) {
+    if ((UseNUMAInterleaving && !FLAG_IS_DEFAULT(UseNUMAInterleaving)) || (UseNUMA && !FLAG_IS_DEFAULT(UseNUMA))) {
+      log_warning(arguments) ("NUMA support for Heap depends on the file system when AllocateHeapAt option is used.\n");
+    }
+  }
   return status;
 }
 
@@ -4304,7 +4428,9 @@
 
 jint Arguments::adjust_after_os() {
   if (UseNUMA) {
-    if (UseParallelGC || UseParallelOldGC) {
+    if (!FLAG_IS_DEFAULT(AllocateHeapAt)) {
+      FLAG_SET_ERGO(bool, UseNUMA, false);
+    } else if (UseParallelGC || UseParallelOldGC) {
       if (FLAG_IS_DEFAULT(MinHeapDeltaBytes)) {
          FLAG_SET_DEFAULT(MinHeapDeltaBytes, 64*M);
       }
--- a/src/hotspot/share/runtime/arguments.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/runtime/arguments.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -27,7 +27,7 @@
 
 #include "logging/logLevel.hpp"
 #include "logging/logTag.hpp"
-#include "memory/allocation.inline.hpp"
+#include "memory/allocation.hpp"
 #include "runtime/java.hpp"
 #include "runtime/os.hpp"
 #include "runtime/perfData.hpp"
@@ -60,60 +60,11 @@
  public:
   char* value() const { return _value; }
 
-  bool set_value(const char *value) {
-    if (_value != NULL) {
-      FreeHeap(_value);
-    }
-    _value = AllocateHeap(strlen(value)+1, mtArguments);
-    assert(_value != NULL, "Unable to allocate space for new path value");
-    if (_value != NULL) {
-      strcpy(_value, value);
-    } else {
-      // not able to allocate
-      return false;
-    }
-    return true;
-  }
+  bool set_value(const char *value);
+  void append_value(const char *value);
 
-  void append_value(const char *value) {
-    char *sp;
-    size_t len = 0;
-    if (value != NULL) {
-      len = strlen(value);
-      if (_value != NULL) {
-        len += strlen(_value);
-      }
-      sp = AllocateHeap(len+2, mtArguments);
-      assert(sp != NULL, "Unable to allocate space for new append path value");
-      if (sp != NULL) {
-        if (_value != NULL) {
-          strcpy(sp, _value);
-          strcat(sp, os::path_separator());
-          strcat(sp, value);
-          FreeHeap(_value);
-        } else {
-          strcpy(sp, value);
-        }
-        _value = sp;
-      }
-    }
-  }
-
-  PathString(const char* value) {
-    if (value == NULL) {
-      _value = NULL;
-    } else {
-      _value = AllocateHeap(strlen(value)+1, mtArguments);
-      strcpy(_value, value);
-    }
-  }
-
-  ~PathString() {
-    if (_value != NULL) {
-      FreeHeap(_value);
-      _value = NULL;
-    }
-  }
+  PathString(const char* value);
+  ~PathString();
 };
 
 // ModulePatchPath records the module/path pair as specified to --patch-module.
@@ -122,24 +73,8 @@
   char* _module_name;
   PathString* _path;
 public:
-  ModulePatchPath(const char* module_name, const char* path) {
-    assert(module_name != NULL && path != NULL, "Invalid module name or path value");
-    size_t len = strlen(module_name) + 1;
-    _module_name = AllocateHeap(len, mtInternal);
-    strncpy(_module_name, module_name, len); // copy the trailing null
-    _path =  new PathString(path);
-  }
-
-  ~ModulePatchPath() {
-    if (_module_name != NULL) {
-      FreeHeap(_module_name);
-      _module_name = NULL;
-    }
-    if (_path != NULL) {
-      delete _path;
-      _path = NULL;
-    }
-  }
+  ModulePatchPath(const char* module_name, const char* path);
+  ~ModulePatchPath();
 
   inline void set_path(const char* path) { _path->set_value(path); }
   inline const char* module_name() const { return _module_name; }
@@ -186,17 +121,7 @@
   }
 
   // Constructor
-  SystemProperty(const char* key, const char* value, bool writeable, bool internal = false) : PathString(value) {
-    if (key == NULL) {
-      _key = NULL;
-    } else {
-      _key = AllocateHeap(strlen(key)+1, mtArguments);
-      strcpy(_key, key);
-    }
-    _next = NULL;
-    _internal = internal;
-    _writeable = writeable;
-  }
+  SystemProperty(const char* key, const char* value, bool writeable, bool internal = false);
 };
 
 
@@ -235,21 +160,7 @@
   void set_invalid()                        { _state = agent_invalid; }
 
   // Constructor
-  AgentLibrary(const char* name, const char* options, bool is_absolute_path, void* os_lib) {
-    _name = AllocateHeap(strlen(name)+1, mtArguments);
-    strcpy(_name, name);
-    if (options == NULL) {
-      _options = NULL;
-    } else {
-      _options = AllocateHeap(strlen(options)+1, mtArguments);
-      strcpy(_options, options);
-    }
-    _is_absolute_path = is_absolute_path;
-    _os_lib = os_lib;
-    _next = NULL;
-    _state = agent_invalid;
-    _is_static_lib = false;
-  }
+  AgentLibrary(const char* name, const char* options, bool is_absolute_path, void* os_lib);
 };
 
 // maintain an order of entry list of AgentLibrary
@@ -421,19 +332,15 @@
 
   // -Xrun arguments
   static AgentLibraryList _libraryList;
-  static void add_init_library(const char* name, char* options)
-    { _libraryList.add(new AgentLibrary(name, options, false, NULL)); }
+  static void add_init_library(const char* name, char* options);
 
   // -agentlib and -agentpath arguments
   static AgentLibraryList _agentList;
-  static void add_init_agent(const char* name, char* options, bool absolute_path)
-    { _agentList.add(new AgentLibrary(name, options, absolute_path, NULL)); }
+  static void add_init_agent(const char* name, char* options, bool absolute_path);
 
   // Late-binding agents not started via arguments
-  static void add_loaded_agent(AgentLibrary *agentLib)
-    { _agentList.add(agentLib); }
-  static void add_loaded_agent(const char* name, char* options, bool absolute_path, void* os_lib)
-    { _agentList.add(new AgentLibrary(name, options, absolute_path, os_lib)); }
+  static void add_loaded_agent(AgentLibrary *agentLib);
+  static void add_loaded_agent(const char* name, char* options, bool absolute_path, void* os_lib);
 
   // Operation modi
   static Mode _mode;
--- a/src/hotspot/share/runtime/globals.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/runtime/globals.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -4083,7 +4083,11 @@
   diagnostic(bool, CompilerDirectivesPrint, false,                          \
              "Print compiler directives on installation.")                  \
   diagnostic(int,  CompilerDirectivesLimit, 50,                             \
-             "Limit on number of compiler directives.")
+             "Limit on number of compiler directives.")                     \
+                                                                            \
+  product(ccstr, AllocateHeapAt, NULL,                                      \
+          "Path to the directoy where a temporary file will be created "    \
+          "to use as the backing store for Java Heap.")
 
 
 /*
--- a/src/hotspot/share/runtime/objectMonitor.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/runtime/objectMonitor.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "classfile/vmSymbols.hpp"
+#include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/markOop.hpp"
 #include "oops/oop.inline.hpp"
@@ -242,6 +243,19 @@
 // * See also http://blogs.sun.com/dave
 
 
+void* ObjectMonitor::operator new (size_t size) throw() {
+  return AllocateHeap(size, mtInternal);
+}
+void* ObjectMonitor::operator new[] (size_t size) throw() {
+  return operator new (size);
+}
+void ObjectMonitor::operator delete(void* p) {
+  FreeHeap(p);
+}
+void ObjectMonitor::operator delete[] (void *p) {
+  operator delete(p);
+}
+
 // -----------------------------------------------------------------------------
 // Enter support
 
--- a/src/hotspot/share/runtime/objectMonitor.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/runtime/objectMonitor.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -25,7 +25,7 @@
 #ifndef SHARE_VM_RUNTIME_OBJECTMONITOR_HPP
 #define SHARE_VM_RUNTIME_OBJECTMONITOR_HPP
 
-#include "memory/allocation.inline.hpp"
+#include "memory/allocation.hpp"
 #include "memory/padded.hpp"
 #include "runtime/os.hpp"
 #include "runtime/park.hpp"
@@ -213,18 +213,10 @@
   static int Knob_VerifyMatch;
   static int Knob_SpinLimit;
 
-  void* operator new (size_t size) throw() {
-    return AllocateHeap(size, mtInternal);
-  }
-  void* operator new[] (size_t size) throw() {
-    return operator new (size);
-  }
-  void operator delete(void* p) {
-    FreeHeap(p);
-  }
-  void operator delete[] (void *p) {
-    operator delete(p);
-  }
+  void* operator new (size_t size) throw();
+  void* operator new[] (size_t size) throw();
+  void operator delete(void* p);
+  void operator delete[] (void *p);
 
   // TODO-FIXME: the "offset" routines should return a type of off_t instead of int ...
   // ByteSize would also be an appropriate type.
--- a/src/hotspot/share/runtime/os.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/runtime/os.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -1665,10 +1665,21 @@
   return os::pd_create_stack_guard_pages(addr, bytes);
 }
 
-char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint) {
-  char* result = pd_reserve_memory(bytes, addr, alignment_hint);
-  if (result != NULL) {
-    MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
+char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint, int file_desc) {
+  char* result = NULL;
+
+  if (file_desc != -1) {
+    // Could have called pd_reserve_memory() followed by replace_existing_mapping_with_file_mapping(),
+    // but AIX may use SHM in which case its more trouble to detach the segment and remap memory to the file.
+    result = os::map_memory_to_file(addr, bytes, file_desc);
+    if (result != NULL) {
+      MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC);
+    }
+  } else {
+    result = pd_reserve_memory(bytes, addr, alignment_hint);
+    if (result != NULL) {
+      MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
+    }
   }
 
   return result;
@@ -1685,10 +1696,18 @@
   return result;
 }
 
-char* os::attempt_reserve_memory_at(size_t bytes, char* addr) {
-  char* result = pd_attempt_reserve_memory_at(bytes, addr);
-  if (result != NULL) {
-    MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
+char* os::attempt_reserve_memory_at(size_t bytes, char* addr, int file_desc) {
+  char* result = NULL;
+  if (file_desc != -1) {
+    result = pd_attempt_reserve_memory_at(bytes, addr, file_desc);
+    if (result != NULL) {
+      MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC);
+    }
+  } else {
+    result = pd_attempt_reserve_memory_at(bytes, addr);
+    if (result != NULL) {
+      MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC);
+    }
   }
   return result;
 }
--- a/src/hotspot/share/runtime/os.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/runtime/os.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -108,8 +108,9 @@
   }
 
   static char*  pd_reserve_memory(size_t bytes, char* addr = 0,
-                               size_t alignment_hint = 0);
+                                  size_t alignment_hint = 0);
   static char*  pd_attempt_reserve_memory_at(size_t bytes, char* addr);
+  static char*  pd_attempt_reserve_memory_at(size_t bytes, char* addr, int file_desc);
   static void   pd_split_reserved_memory(char *base, size_t size,
                                       size_t split, bool realloc);
   static bool   pd_commit_memory(char* addr, size_t bytes, bool executable);
@@ -310,11 +311,11 @@
 
   static int    vm_allocation_granularity();
   static char*  reserve_memory(size_t bytes, char* addr = 0,
-                               size_t alignment_hint = 0);
+                               size_t alignment_hint = 0, int file_desc = -1);
   static char*  reserve_memory(size_t bytes, char* addr,
                                size_t alignment_hint, MEMFLAGS flags);
-  static char*  reserve_memory_aligned(size_t size, size_t alignment);
-  static char*  attempt_reserve_memory_at(size_t bytes, char* addr);
+  static char*  reserve_memory_aligned(size_t size, size_t alignment, int file_desc = -1);
+  static char*  attempt_reserve_memory_at(size_t bytes, char* addr, int file_desc = -1);
   static void   split_reserved_memory(char *base, size_t size,
                                       size_t split, bool realloc);
   static bool   commit_memory(char* addr, size_t bytes, bool executable);
@@ -345,6 +346,14 @@
   static bool   create_stack_guard_pages(char* addr, size_t bytes);
   static bool   pd_create_stack_guard_pages(char* addr, size_t bytes);
   static bool   remove_stack_guard_pages(char* addr, size_t bytes);
+  // Helper function to create a new file with template jvmheap.XXXXXX.
+  // Returns a valid fd on success or else returns -1
+  static int create_file_for_heap(const char* dir);
+  // Map memory to the file referred by fd. This function is slightly different from map_memory()
+  // and is added to be used for implementation of -XX:AllocateHeapAt
+  static char* map_memory_to_file(char* base, size_t size, int fd);
+  // Replace existing reserved memory with file mapping
+  static char* replace_existing_mapping_with_file_mapping(char* base, size_t size, int fd);
 
   static char*  map_memory(int fd, const char* file_name, size_t file_offset,
                            char *addr, size_t bytes, bool read_only = false,
--- a/src/hotspot/share/runtime/park.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/runtime/park.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -23,10 +23,9 @@
  */
 
 #include "precompiled.hpp"
+#include "memory/allocation.inline.hpp"
 #include "runtime/thread.hpp"
 
-
-
 // Lifecycle management for TSM ParkEvents.
 // ParkEvents are type-stable (TSM).
 // In our particular implementation they happen to be immortal.
--- a/src/hotspot/share/services/diagnosticArgument.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/services/diagnosticArgument.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -29,6 +29,29 @@
 #include "runtime/thread.hpp"
 #include "services/diagnosticArgument.hpp"
 
+StringArrayArgument::StringArrayArgument() {
+  _array = new(ResourceObj::C_HEAP, mtInternal)GrowableArray<char *>(32, true);
+  assert(_array != NULL, "Sanity check");
+}
+
+StringArrayArgument::~StringArrayArgument() {
+  for (int i=0; i<_array->length(); i++) {
+    if(_array->at(i) != NULL) { // Safety check
+      FREE_C_HEAP_ARRAY(char, _array->at(i));
+    }
+  }
+  delete _array;
+}
+
+void StringArrayArgument::add(const char* str, size_t len) {
+  if (str != NULL) {
+    char* ptr = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
+    strncpy(ptr, str, len);
+    ptr[len] = 0;
+    _array->append(ptr);
+  }
+}
+
 void GenDCmdArgument::read_value(const char* str, size_t len, TRAPS) {
   /* NOTE:Some argument types doesn't require a value,
    * for instance boolean arguments: "enableFeatureX". is
--- a/src/hotspot/share/services/diagnosticArgument.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/services/diagnosticArgument.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -35,29 +35,14 @@
 private:
   GrowableArray<char*>* _array;
 public:
-  StringArrayArgument() {
-    _array = new(ResourceObj::C_HEAP, mtInternal)GrowableArray<char *>(32, true);
-    assert(_array != NULL, "Sanity check");
-  }
-  void add(const char* str, size_t len) {
-    if (str != NULL) {
-      char* ptr = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
-      strncpy(ptr, str, len);
-      ptr[len] = 0;
-      _array->append(ptr);
-    }
-  }
+  StringArrayArgument();
+  ~StringArrayArgument();
+
+  void add(const char* str, size_t len);
+
   GrowableArray<char*>* array() {
     return _array;
   }
-  ~StringArrayArgument() {
-    for (int i=0; i<_array->length(); i++) {
-      if(_array->at(i) != NULL) { // Safety check
-        FREE_C_HEAP_ARRAY(char, _array->at(i));
-      }
-    }
-    delete _array;
-  }
 };
 
 class NanoTimeArgument {
--- a/src/hotspot/share/utilities/decoder.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/utilities/decoder.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "jvm.h"
+#include "memory/allocation.inline.hpp"
 #include "runtime/os.hpp"
 #include "utilities/decoder.hpp"
 #include "utilities/vmError.hpp"
--- a/src/hotspot/share/utilities/decoder_elf.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/utilities/decoder_elf.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -26,6 +26,7 @@
 
 #if !defined(_WINDOWS) && !defined(__APPLE__)
 #include "decoder_elf.hpp"
+#include "memory/allocation.inline.hpp"
 
 ElfDecoder::~ElfDecoder() {
   if (_opened_elf_files != NULL) {
--- a/src/hotspot/share/utilities/growableArray.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/utilities/growableArray.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/thread.inline.hpp"
 #include "utilities/growableArray.hpp"
@@ -56,3 +57,7 @@
     return _arena->Amalloc(byte_size);
   }
 }
+
+void GenericGrowableArray::free_C_heap(void* elements) {
+  FreeHeap(elements);
+}
--- a/src/hotspot/share/utilities/growableArray.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/utilities/growableArray.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -26,9 +26,9 @@
 #define SHARE_VM_UTILITIES_GROWABLEARRAY_HPP
 
 #include "memory/allocation.hpp"
-#include "memory/allocation.inline.hpp"
 #include "utilities/debug.hpp"
 #include "utilities/globalDefinitions.hpp"
+#include "utilities/ostream.hpp"
 
 // A growable array.
 
@@ -144,6 +144,8 @@
     assert(on_stack(), "fast ResourceObj path only");
     return (void*)resource_allocate_bytes(thread, elementSize * _max);
   }
+
+  void free_C_heap(void* elements);
 };
 
 template<class E> class GrowableArrayIterator;
@@ -451,7 +453,7 @@
     for (     ; i < _max; i++) ::new ((void*)&newData[i]) E();
     for (i = 0; i < old_max; i++) _data[i].~E();
     if (on_C_heap() && _data != NULL) {
-      FreeHeap(_data);
+      free_C_heap(_data);
     }
     _data = newData;
 }
@@ -475,7 +477,7 @@
     clear();
     if (_data != NULL) {
       for (int i = 0; i < _max; i++) _data[i].~E();
-      FreeHeap(_data);
+      free_C_heap(_data);
       _data = NULL;
     }
 }
--- a/src/hotspot/share/utilities/stack.hpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/hotspot/share/utilities/stack.hpp	Thu Nov 30 09:51:28 2017 -0500
@@ -26,7 +26,6 @@
 #define SHARE_VM_UTILITIES_STACK_HPP
 
 #include "memory/allocation.hpp"
-#include "memory/allocation.inline.hpp"
 
 // Class Stack (below) grows and shrinks by linking together "segments" which
 // are allocated on demand.  Segments are arrays of the element type (E) plus an
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/PackageNameFilter.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/PackageNameFilter.java	Thu Nov 30 09:51:28 2017 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, 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
@@ -50,10 +50,14 @@
     }
 
     public boolean canInclude(InstanceKlass kls) {
-        String klassName = kls.getName().asString().replace('/', '.');
+        if (pkgList == null) {
+            // Dump everything
+            return true;
+        }
         final int len = pkgList.length;
         if (len == 0)
             return true;
+        String klassName = kls.getName().asString().replace('/', '.');
         for (int i=0; i < len; i++)
             if (klassName.startsWith((String) pkgList[i] )) return true;
         return false;
--- a/test/hotspot/gtest/logging/test_logMessageTest.cpp	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/gtest/logging/test_logMessageTest.cpp	Thu Nov 30 09:51:28 2017 -0500
@@ -27,6 +27,7 @@
 #include "logTestUtils.inline.hpp"
 #include "logging/log.hpp"
 #include "logging/logMessage.hpp"
+#include "memory/allocation.inline.hpp"
 #include "unittest.hpp"
 #include "utilities/globalDefinitions.hpp"
 
--- a/test/hotspot/jtreg/TEST.ROOT	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/TEST.ROOT	Thu Nov 30 09:51:28 2017 -0500
@@ -53,6 +53,7 @@
     vm.rtm.os \
     vm.aot \
     vm.cds \
+    vm.cds.custom.loaders \
     vm.graal.enabled \
     docker.support
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/TestAllocateHeapAt.java	Thu Nov 30 09:51:28 2017 -0500
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017, 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 TestAllocateHeapAt.java
+ * @key gc
+ * @summary Test to check allocation of Java Heap with AllocateHeapAt option
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ */
+
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import java.util.ArrayList;
+import java.util.Collections;
+
+public class TestAllocateHeapAt {
+  public static void main(String args[]) throws Exception {
+    ArrayList<String> vmOpts = new ArrayList();
+
+    String testVmOptsStr = System.getProperty("test.java.opts");
+    if (!testVmOptsStr.isEmpty()) {
+      String[] testVmOpts = testVmOptsStr.split(" ");
+      Collections.addAll(vmOpts, testVmOpts);
+    }
+    String test_dir = System.getProperty("test.dir", ".");
+    Collections.addAll(vmOpts, new String[] {"-XX:AllocateHeapAt=" + test_dir,
+                                             "-Xlog:gc+heap=info",
+                                             "-Xmx32m",
+                                             "-Xms32m",
+                                             "-version"});
+
+    System.out.print("Testing:\n" + JDKToolFinder.getJDKTool("java"));
+    for (int i = 0; i < vmOpts.size(); i += 1) {
+      System.out.print(" " + vmOpts.get(i));
+    }
+    System.out.println();
+
+    ProcessBuilder pb =
+      ProcessTools.createJavaProcessBuilder(vmOpts.toArray(new String[vmOpts.size()]));
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+    System.out.println("Output:\n" + output.getOutput());
+
+    output.shouldContain("Successfully allocated Java heap at location");
+    output.shouldHaveExitValue(0);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/TestAllocateHeapAtError.java	Thu Nov 30 09:51:28 2017 -0500
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017, 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 TestAllocateHeapAtError.java
+ * @key gc
+ * @summary Test to check correct handling of non-existent directory passed to AllocateHeapAt option
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ */
+
+import java.io.File;
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.UUID;
+
+public class TestAllocateHeapAtError {
+  public static void main(String args[]) throws Exception {
+    ArrayList<String> vmOpts = new ArrayList();
+
+    String testVmOptsStr = System.getProperty("test.java.opts");
+    if (!testVmOptsStr.isEmpty()) {
+      String[] testVmOpts = testVmOptsStr.split(" ");
+      Collections.addAll(vmOpts, testVmOpts);
+    }
+    String test_dir = System.getProperty("test.dir", ".");
+
+    File f = null;
+    do {
+      f = new File(test_dir, UUID.randomUUID().toString());
+    } while(f.exists());
+
+    Collections.addAll(vmOpts, new String[] {"-XX:AllocateHeapAt=" + f.getName(),
+                                             "-Xlog:gc+heap=info",
+                                             "-Xmx32m",
+                                             "-Xms32m",
+                                             "-version"});
+
+    System.out.print("Testing:\n" + JDKToolFinder.getJDKTool("java"));
+    for (int i = 0; i < vmOpts.size(); i += 1) {
+      System.out.print(" " + vmOpts.get(i));
+    }
+    System.out.println();
+
+    ProcessBuilder pb =
+      ProcessTools.createJavaProcessBuilder(vmOpts.toArray(new String[vmOpts.size()]));
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+    System.out.println("Output:\n" + output.getOutput());
+
+    output.shouldContain("Could not create file for Heap");
+    output.shouldContain("Error occurred during initialization of VM");
+    output.shouldNotHaveExitValue(0);
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/TestAllocateHeapAtMultiple.java	Thu Nov 30 09:51:28 2017 -0500
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017, 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 TestAllocateHeapAtMultiple.java
+ * @key gc
+ * @summary Test to check allocation of Java Heap with AllocateHeapAt option. Has multiple sub-tests to cover different code paths.
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @requires vm.bits == "64"
+ */
+
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import java.util.ArrayList;
+import java.util.Collections;
+
+public class TestAllocateHeapAtMultiple {
+  public static void main(String args[]) throws Exception {
+    ArrayList<String> vmOpts = new ArrayList();
+    String[] testVmOpts = null;
+
+    String test_dir = System.getProperty("test.dir", ".");
+
+    String testVmOptsStr = System.getProperty("test.java.opts");
+    if (!testVmOptsStr.isEmpty()) {
+      testVmOpts = testVmOptsStr.split(" ");
+    }
+
+    // Extra options for each of the sub-tests
+    String[] extraOptsList = new String[] {
+      "-Xmx32m -Xms32m -XX:+UseCompressedOops",     // 1. With compressedoops enabled.
+      "-Xmx32m -Xms32m -XX:-UseCompressedOops",     // 2. With compressedoops disabled.
+      "-Xmx32m -Xms32m -XX:HeapBaseMinAddress=3g",  // 3. With user specified HeapBaseMinAddress.
+      "-Xmx4g -Xms4g",                              // 4. With larger heap size (UnscaledNarrowOop not possible).
+      "-Xmx4g -Xms4g -XX:+UseLargePages",           // 5. Set UseLargePages.
+      "-Xmx4g -Xms4g -XX:+UseNUMA"                  // 6. Set UseNUMA.
+    };
+
+    for(String extraOpts : extraOptsList) {
+      vmOpts.clear();
+      if(testVmOpts != null) {
+        Collections.addAll(vmOpts, testVmOpts);
+      }
+      // Add extra options specific to the sub-test.
+      String[] extraOptsArray = extraOpts.split(" ");
+      if(extraOptsArray != null) {
+        Collections.addAll(vmOpts, extraOptsArray);
+      }
+      // Add common options
+      Collections.addAll(vmOpts, new String[] {"-XX:AllocateHeapAt=" + test_dir,
+                                               "-Xlog:gc+heap=info",
+                                               "-version"});
+
+      System.out.print("Testing:\n" + JDKToolFinder.getJDKTool("java"));
+      for (int i = 0; i < vmOpts.size(); i += 1) {
+        System.out.print(" " + vmOpts.get(i));
+      }
+      System.out.println();
+
+      ProcessBuilder pb =
+        ProcessTools.createJavaProcessBuilder(vmOpts.toArray(new String[vmOpts.size()]));
+      OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+      System.out.println("Output:\n" + output.getOutput());
+
+      output.shouldContain("Successfully allocated Java heap at location");
+      output.shouldHaveExitValue(0);
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithAllocateHeapAt.java	Thu Nov 30 09:51:28 2017 -0500
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016, 2017, 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.
+ *
+ */
+
+import java.io.IOException;
+
+/*
+ * @test TestGCBasherWithAllocateHeapAt
+ * @key gc
+ * @key stress
+ * @requires vm.gc.G1
+ * @requires vm.flavor == "server" & !vm.emulatedClient
+ * @summary Stress Java heap allocation with AllocateHeapAt flag using GC basher.
+ * @run main/othervm/timeout=500 -Xlog:gc*=info -Xmx256m -server -XX:+UseG1GC -XX:AllocateHeapAt=. TestGCBasherWithAllocateHeapAt 120000
+ */
+public class TestGCBasherWithAllocateHeapAt {
+    public static void main(String[] args) throws IOException {
+        TestGCBasher.main(args);
+    }
+}
--- a/test/hotspot/jtreg/runtime/appcds/DumpClassList.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/DumpClassList.java	Thu Nov 30 09:51:28 2017 -0500
@@ -93,11 +93,11 @@
         output = TestCommon.createArchive(appJar, appClass,
                                           "-Xbootclasspath/a:" + appendJar,
                                           "-XX:+UnlockDiagnosticVMOptions",
-                                          "-XX:+PrintSystemDictionaryAtExit",
+                                          "-Xlog:class+load",
                                           "-XX:SharedClassListFile=" + classList);
         TestCommon.checkDump(output)
             .shouldNotContain("Preload Warning: Cannot find java/lang/invoke/LambdaForm")
             .shouldNotContain("Preload Warning: Cannot find boot/append/Foo")
-            .shouldContain("boot.append.Foo, loader <shared, not restored>");
+            .shouldContain("[info][class,load] boot.append.Foo");
     }
 }
--- a/test/hotspot/jtreg/runtime/appcds/ProhibitedPackage.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/ProhibitedPackage.java	Thu Nov 30 09:51:28 2017 -0500
@@ -27,6 +27,7 @@
  * @summary AppCDS handling of prohibited package.
  * AppCDS does not support uncompressed oops
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
+ * @requires vm.cds
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
  *          java.management
@@ -45,10 +46,8 @@
 
         String appJar = TestCommon.getTestJar("prohibited_pkg.jar");
 
-        // AppCDS for custom loader is only supported on linux-x64 and
-        // Solaris 64-bit platforms.
-        if ((Platform.isLinux() || Platform.isSolaris()) &&
-            Platform.is64bit()) {
+        // Test support for customer loaders
+        if (Platform.areCustomLoadersSupportedForCDS()) {
             String classlist[] = new String[] {
                 "java/lang/Object id: 1",
                 "java/lang/Prohibited id: 2 super: 1 source: " + appJar
@@ -56,11 +55,9 @@
 
             // Make sure a class in a prohibited package for a custom loader
             // will be ignored during dumping.
-            TestCommon.dump(appJar,
-                            classlist,
-                            "-XX:+PrintSystemDictionaryAtExit")
+            TestCommon.dump(appJar,  classlist, "-Xlog:cds")
                 .shouldContain("Dumping")
-                .shouldNotContain("java.lang.Prohibited")
+                .shouldContain("[cds] Prohibited package for non-bootstrap classes: java/lang/Prohibited.class")
                 .shouldHaveExitValue(0);
         }
 
@@ -69,9 +66,9 @@
         // will be ignored during dumping.
         TestCommon.dump(appJar,
                         TestCommon.list("java/lang/Prohibited", "ProhibitedHelper"),
-                        "-XX:+PrintSystemDictionaryAtExit")
+                        "-Xlog:class+load")
             .shouldContain("Dumping")
-            .shouldNotContain("java.lang.Prohibited")
+            .shouldNotContain("[info][class,load] java.lang.Prohibited source: ")
             .shouldHaveExitValue(0);
 
         // Try loading the class in a prohibited package with various -Xshare
--- a/test/hotspot/jtreg/runtime/appcds/TestCommon.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/TestCommon.java	Thu Nov 30 09:51:28 2017 -0500
@@ -321,19 +321,4 @@
         }
         return dirFile.getPath();
     }
-
-
-    // Returns true if custom loader is supported, based on a platform.
-    // Custom loader AppCDS is only supported for Linux-x64 and Solaris.
-    public static boolean isCustomLoaderSupported() {
-        boolean isLinux = Platform.isLinux();
-        boolean isX64 = Platform.isX64();
-        boolean isSolaris = Platform.isSolaris();
-
-        System.out.println("isCustomLoaderSupported: isX64 = " + isX64);
-        System.out.println("isCustomLoaderSupported: isLinux = " + isLinux);
-        System.out.println("isCustomLoaderSupported: isSolaris = " + isSolaris);
-
-        return ((isX64 && isLinux) || isSolaris);
-    }
 }
--- a/test/hotspot/jtreg/runtime/appcds/cacheObject/CheckCachedResolvedReferences.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/CheckCachedResolvedReferences.java	Thu Nov 30 09:51:28 2017 -0500
@@ -26,8 +26,7 @@
  * @test
  * @summary Test resolved_references
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
- * @requires (sun.arch.data.model == "64")
- * @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
+ * @requires vm.cds.custom.loaders
  * @requires (vm.gc=="null")
  * @library /test/lib /test/hotspot/jtreg/runtime/appcds
  * @modules java.base/jdk.internal.misc
@@ -53,9 +52,9 @@
         String helloJarPath = ClassFileInstaller.getJarPath("hello.jar");
 
         String classlist[] = new String[] {
-            "CheckCachedResolvedReferencesApp",
-            "java/lang/Object id: 1",
-            "Hello id: 2 super: 1 source: " + helloJarPath
+            "CheckCachedResolvedReferencesApp",            // built-in app loader
+            "java/lang/Object id: 1",                      // boot loader
+            "Hello id: 2 super: 1 source: " + helloJarPath // custom loader
         };
 
         TestCommon.testDump(appJar, classlist, use_whitebox_jar);
--- a/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatA.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatA.java	Thu Nov 30 09:51:28 2017 -0500
@@ -28,8 +28,7 @@
  *
  * (NOTE: AppCDS does not support uncompressed oops)
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
- * @requires (sun.arch.data.model == "64")
- * @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
+ * @requires vm.cds.custom.loaders
  * @library /test/lib /test/hotspot/jtreg/runtime/appcds
  * @modules java.base/jdk.internal.misc
  *          java.management
--- a/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatB.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatB.java	Thu Nov 30 09:51:28 2017 -0500
@@ -28,8 +28,7 @@
  *
  * (NOTE: AppCDS does not support uncompressed oops)
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
- * @requires (sun.arch.data.model == "64")
- * @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
+ * @requires vm.cds.custom.loaders
  * @library /test/lib /test/hotspot/jtreg/runtime/appcds
  * @modules java.base/jdk.internal.misc
  *          java.management
--- a/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatC.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatC.java	Thu Nov 30 09:51:28 2017 -0500
@@ -28,8 +28,7 @@
  *
  * (NOTE: AppCDS does not support uncompressed oops)
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
- * @requires (sun.arch.data.model == "64")
- * @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
+ * @requires vm.cds.custom.loaders
  * @library /test/lib /test/hotspot/jtreg/runtime/appcds
  * @modules java.base/jdk.internal.misc
  *          java.management
--- a/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatD.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatD.java	Thu Nov 30 09:51:28 2017 -0500
@@ -28,8 +28,7 @@
  *
  * (NOTE: AppCDS does not support uncompressed oops)
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
- * @requires (sun.arch.data.model == "64")
- * @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
+ * @requires vm.cds.custom.loaders
  * @library /test/lib /test/hotspot/jtreg/runtime/appcds
  * @modules java.base/jdk.internal.misc
  *          java.management
--- a/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatE.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/customLoader/ClassListFormatE.java	Thu Nov 30 09:51:28 2017 -0500
@@ -28,8 +28,7 @@
  *
  * (NOTE: AppCDS does not support uncompressed oops)
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
- * @requires (sun.arch.data.model == "64")
- * @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
+ * @requires vm.cds.custom.loaders
  * @library /test/lib /test/hotspot/jtreg/runtime/appcds
  * @modules java.base/jdk.internal.misc
  *          java.management
--- a/test/hotspot/jtreg/runtime/appcds/customLoader/HelloCustom.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/customLoader/HelloCustom.java	Thu Nov 30 09:51:28 2017 -0500
@@ -27,8 +27,7 @@
  * @summary Hello World test for AppCDS custom loader support
  * (NOTE: AppCDS does not support uncompressed oops)
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
- * @requires (sun.arch.data.model == "64")
- * @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
+ * @requires vm.cds.custom.loaders
  * @library /test/lib /test/hotspot/jtreg/runtime/appcds
  * @modules java.base/jdk.internal.misc
  *          java.management
--- a/test/hotspot/jtreg/runtime/appcds/customLoader/LoaderSegregationTest.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/customLoader/LoaderSegregationTest.java	Thu Nov 30 09:51:28 2017 -0500
@@ -28,8 +28,7 @@
  *          custom loader classes.
  * (NOTE: AppCDS does not support uncompressed oops)
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
- * @requires (sun.arch.data.model == "64")
- * @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
+ * @requires vm.cds.custom.loaders
  * @library /test/lib /test/hotspot/jtreg/runtime/appcds
  * @modules java.base/jdk.internal.misc
  *          java.management
--- a/test/hotspot/jtreg/runtime/appcds/customLoader/ParallelTestMultiFP.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/customLoader/ParallelTestMultiFP.java	Thu Nov 30 09:51:28 2017 -0500
@@ -27,8 +27,7 @@
  * @summary Load classes from CDS archive into multiple custom loader using parallel threads
  * (NOTE: AppCDS does not support uncompressed oops)
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
- * @requires (sun.arch.data.model == "64")
- * @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
+ * @requires vm.cds.custom.loaders
  * @library /test/lib /test/hotspot/jtreg/runtime/appcds
  * @modules java.base/jdk.internal.misc
  *          java.management
--- a/test/hotspot/jtreg/runtime/appcds/customLoader/ParallelTestSingleFP.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/customLoader/ParallelTestSingleFP.java	Thu Nov 30 09:51:28 2017 -0500
@@ -27,8 +27,7 @@
  * @summary Load classes from CDS archive into a single custom loader using parallel threads (finger print)
  * (NOTE: AppCDS does not support uncompressed oops)
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
- * @requires (sun.arch.data.model == "64")
- * @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
+ * @requires vm.cds.custom.loaders
  * @library /test/lib /test/hotspot/jtreg/runtime/appcds
  * @modules java.base/jdk.internal.misc
  *          java.management
--- a/test/hotspot/jtreg/runtime/appcds/customLoader/ProhibitedPackageNamesTest.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/customLoader/ProhibitedPackageNamesTest.java	Thu Nov 30 09:51:28 2017 -0500
@@ -27,8 +27,7 @@
  * @summary Make sure prohibited packages cannot be stored into archive for custom loaders.
  * (NOTE: AppCDS does not support uncompressed oops)
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
- * @requires (sun.arch.data.model == "64")
- * @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
+ * @requires vm.cds.custom.loaders
  * @library /test/lib /test/hotspot/jtreg/runtime/appcds
  * @modules java.base/jdk.internal.misc
  *          java.management
--- a/test/hotspot/jtreg/runtime/appcds/customLoader/ProtectionDomain.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/customLoader/ProtectionDomain.java	Thu Nov 30 09:51:28 2017 -0500
@@ -28,8 +28,7 @@
  *
  * AppCDS does not support uncompressed oops
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
- * @requires (sun.arch.data.model == "64")
- * @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
+ * @requires vm.cds.custom.loaders
  *
  * @library /test/lib /test/hotspot/jtreg/runtime/appcds
  * @modules java.base/jdk.internal.misc
--- a/test/hotspot/jtreg/runtime/appcds/customLoader/SameNameInTwoLoadersTest.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/customLoader/SameNameInTwoLoadersTest.java	Thu Nov 30 09:51:28 2017 -0500
@@ -28,8 +28,7 @@
  *
  * (NOTE: AppCDS does not support uncompressed oops)
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
- * @requires (sun.arch.data.model == "64")
- * @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
+ * @requires vm.cds.custom.loaders
  *
  * @library /test/lib /test/hotspot/jtreg/runtime/appcds
  * @modules java.base/jdk.internal.misc
--- a/test/hotspot/jtreg/runtime/appcds/customLoader/UnintendedLoadersTest.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/customLoader/UnintendedLoadersTest.java	Thu Nov 30 09:51:28 2017 -0500
@@ -27,8 +27,7 @@
  * @summary Make sure classes intended for custom loaders cannot be loaded by BOOT/EXT/APP loaders
  * (NOTE: AppCDS does not support uncompressed oops)
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
- * @requires (sun.arch.data.model == "64")
- * @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
+ * @requires vm.cds.custom.loaders
  * @library /test/lib /test/hotspot/jtreg/runtime/appcds
  * @modules java.base/jdk.internal.misc
  *          java.management
--- a/test/hotspot/jtreg/runtime/appcds/customLoader/UnloadUnregisteredLoaderTest.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/customLoader/UnloadUnregisteredLoaderTest.java	Thu Nov 30 09:51:28 2017 -0500
@@ -28,8 +28,7 @@
  *          unloaded.
  * (NOTE: AppCDS does not support uncompressed oops)
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
- * @requires (sun.arch.data.model == "64")
- * @requires ((os.family == "linux") & (os.arch=="amd64")) | (os.family == "solaris")
+ * @requires vm.cds.custom.loaders
  * @library /test/lib /test/hotspot/jtreg/runtime/appcds /test/hotspot/jtreg/runtime/testlibrary
  * @modules java.base/jdk.internal.misc
  *          java.management
--- a/test/hotspot/jtreg/runtime/appcds/customLoader/UnsupportedPlatforms.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/customLoader/UnsupportedPlatforms.java	Thu Nov 30 09:51:28 2017 -0500
@@ -25,9 +25,9 @@
 /*
  * @test
  * @summary Ensure that support for AppCDS custom class loaders are not enabled on unsupported platforms.
- * The only supported platforms are Linux/AMD64 and 64-bit Solaris.
  * (NOTE: AppCDS does not support uncompressed oops)
  * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
+ * @requires vm.cds
  * @library /test/lib /test/hotspot/jtreg/runtime/appcds
  * @modules java.base/jdk.internal.misc
  *          java.management
@@ -55,8 +55,7 @@
 
         OutputAnalyzer out = TestCommon.dump(appJar, classlist);
 
-        if ((Platform.isSolaris() && Platform.is64bit()) ||
-            (Platform.isLinux() && Platform.isX64())) {
+        if (Platform.areCustomLoadersSupportedForCDS()) {
             out.shouldNotContain(PLATFORM_NOT_SUPPORTED_WARNING);
             out.shouldHaveExitValue(0);
         } else {
--- a/test/hotspot/jtreg/runtime/appcds/jvmti/transformRelatedClasses/TransformRelatedClassesAppCDS.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/runtime/appcds/jvmti/transformRelatedClasses/TransformRelatedClassesAppCDS.java	Thu Nov 30 09:51:28 2017 -0500
@@ -39,6 +39,7 @@
 
 import java.io.File;
 import java.util.ArrayList;
+import jdk.test.lib.Platform;
 import jdk.test.lib.process.OutputAnalyzer;
 
 // This class is intended to test 2 parent-child relationships:
@@ -148,7 +149,7 @@
 
 
     private void runWithCustomLoader(ArrayList<TestEntry> testTable) throws Exception {
-        if (!TestCommon.isCustomLoaderSupported()) {
+        if (!Platform.areCustomLoadersSupportedForCDS()) {
             log("custom loader not supported for this platform" +
                 " - skipping test case for custom loader");
             return;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbAttach.java	Thu Nov 30 09:51:28 2017 -0500
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import jdk.test.lib.apps.LingeredApp;
+
+/*
+ * @test
+ * @bug 8191658
+ * @summary Test clhsdb attach, detach, reattach commands
+ * @library /test/lib
+ * @run main/othervm ClhsdbAttach
+ */
+
+public class ClhsdbAttach {
+
+    public static void main(String[] args) throws Exception {
+        System.out.println("Starting ClhsdbAttach test");
+
+        LingeredApp theApp = null;
+        try {
+            ClhsdbLauncher test = new ClhsdbLauncher();
+            theApp = LingeredApp.startApp();
+            System.out.println("Started LingeredApp with pid " + theApp.getPid());
+            String attach = "attach " + theApp.getPid();
+
+            List<String> cmds = List.of(
+                    "where",
+                    attach,
+                    "flags MaxJavaStackTraceDepth",
+                    "detach",
+                    "universe",
+                    "reattach",
+                    "longConstant markOopDesc::locked_value");
+
+            Map<String, List<String>> expStrMap = new HashMap<>();
+            expStrMap.put("where", List.of(
+                    "Command not valid until attached to a VM"));
+            expStrMap.put("flags MaxJavaStackTraceDepth", List.of(
+                    "MaxJavaStackTraceDepth = "));
+            expStrMap.put("universe", List.of(
+                    "Command not valid until attached to a VM"));
+            expStrMap.put("longConstant markOopDesc::locked_value", List.of(
+                    "longConstant markOopDesc::locked_value"));
+
+            test.run(-1, cmds, expStrMap, null);
+        } catch (Exception ex) {
+            throw new RuntimeException("Test ERROR " + ex, ex);
+        } finally {
+            LingeredApp.stopApp(theApp);
+        }
+        System.out.println("Test PASSED");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbJhisto.java	Thu Nov 30 09:51:28 2017 -0500
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import jdk.test.lib.apps.LingeredApp;
+import jdk.test.lib.Utils;
+
+/*
+ * @test
+ * @bug 8191658
+ * @summary Test clhsdb jhisto command
+ * @library /test/lib
+ * @run main/othervm ClhsdbJhisto
+ */
+
+public class ClhsdbJhisto {
+
+    public static void main(String[] args) throws Exception {
+        System.out.println("Starting ClhsdbJhisto test");
+
+        LingeredAppWithInterface theApp = null;
+        try {
+            ClhsdbLauncher test = new ClhsdbLauncher();
+            List<String> vmArgs = new ArrayList<String>();
+            vmArgs.addAll(Utils.getVmOptions());
+
+            theApp = new LingeredAppWithInterface();
+            LingeredApp.startApp(vmArgs, theApp);
+            System.out.println("Started LingeredApp with pid " + theApp.getPid());
+
+            List<String> cmds = List.of("jhisto");
+
+            Map<String, List<String>> expStrMap = new HashMap<>();
+            expStrMap.put("jhisto", List.of(
+                    "java.lang.String",
+                    "java.util.HashMap",
+                    "java.lang.Class",
+                    "java.nio.HeapByteBuffer",
+                    "java.net.URI",
+                    "LingeredAppWithInterface",
+                    "ParselTongue",
+                    "ImmutableCollections$SetN$1"));
+
+            test.run(theApp.getPid(), cmds, expStrMap, null);
+        } catch (Exception ex) {
+            throw new RuntimeException("Test ERROR " + ex, ex);
+        } finally {
+            LingeredApp.stopApp(theApp);
+        }
+        System.out.println("Test PASSED");
+    }
+}
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java	Thu Nov 30 09:51:28 2017 -0500
@@ -53,10 +53,12 @@
     private void attach(long lingeredAppPid)
         throws IOException {
 
-        System.out.println("Starting clhsdb against " + lingeredAppPid);
         JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");
         launcher.addToolArg("clhsdb");
-        launcher.addToolArg("--pid=" + Long.toString(lingeredAppPid));
+        if (lingeredAppPid != -1) {
+            launcher.addToolArg("--pid=" + Long.toString(lingeredAppPid));
+            System.out.println("Starting clhsdb against " + lingeredAppPid);
+        }
 
         ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());
         processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/TestClassDump.java	Thu Nov 30 09:51:28 2017 -0500
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import jdk.test.lib.apps.LingeredApp;
+import jdk.test.lib.Platform;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+/*
+ * @test
+ * @bug 8184982
+ * @summary Test ClassDump tool
+ * @library /test/lib
+ * @run main/othervm TestClassDump
+ */
+
+public class TestClassDump {
+
+    private static void dumpClass(long lingeredAppPid)
+        throws IOException {
+
+        ProcessBuilder pb;
+        OutputAnalyzer output;
+
+        pb = ProcessTools.createJavaProcessBuilder(
+                "-Dsun.jvm.hotspot.tools.jcore.outputDir=jtreg_classes",
+                "-m", "jdk.hotspot.agent/sun.jvm.hotspot.tools.jcore.ClassDump", String.valueOf(lingeredAppPid));
+        output = new OutputAnalyzer(pb.start());
+        output.shouldHaveExitValue(0);
+        if (!Files.isDirectory(Paths.get("jtreg_classes"))) {
+            throw new RuntimeException("jtreg_classes directory not found");
+        }
+        if (Files.notExists(Paths.get("jtreg_classes", "java", "lang", "Integer.class"))) {
+            throw new RuntimeException("jtreg_classes/java/lang/Integer.class not found");
+        }
+        if (Files.notExists(Paths.get("jtreg_classes", "jdk", "test", "lib", "apps", "LingeredApp.class"))) {
+            throw new RuntimeException("jtreg_classes/jdk/test/lib/apps/LingeredApp.class not found");
+        }
+        if (Files.notExists(Paths.get("jtreg_classes", "sun", "net", "util", "URLUtil.class"))) {
+            throw new RuntimeException("jtreg_classes/sun/net/util/URLUtil.class not found");
+        }
+
+        pb = ProcessTools.createJavaProcessBuilder(
+                "-Dsun.jvm.hotspot.tools.jcore.outputDir=jtreg_classes2",
+                "-Dsun.jvm.hotspot.tools.jcore.PackageNameFilter.pkgList=jdk,sun",
+                "-m", "jdk.hotspot.agent/sun.jvm.hotspot.tools.jcore.ClassDump", String.valueOf(lingeredAppPid));
+        output = new OutputAnalyzer(pb.start());
+        output.shouldHaveExitValue(0);
+        if (Files.exists(Paths.get("jtreg_classes2", "java", "math", "BigInteger.class"))) {
+            throw new RuntimeException("jtreg_classes2/java/math/BigInteger.class not expected");
+        }
+        if (Files.notExists(Paths.get("jtreg_classes2", "sun", "util", "calendar", "BaseCalendar.class"))) {
+            throw new RuntimeException("jtreg_classes2/sun/util/calendar/BaseCalendar.class not found");
+        }
+        if (Files.notExists(Paths.get("jtreg_classes2", "jdk", "internal", "vm", "PostVMInitHook.class"))) {
+            throw new RuntimeException("jtreg_classes2/jdk/internal/vm/PostVMInitHook.class not found");
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (!Platform.shouldSAAttach()) {
+            // Silently skip the test if we don't have enough permissions to attach
+            System.out.println("SA attach not expected to work - test skipped.");
+            return;
+        }
+
+        LingeredApp theApp = null;
+        try {
+            theApp = LingeredApp.startApp();
+            long pid = theApp.getPid();
+            System.out.println("Started LingeredApp with pid " + pid);
+            dumpClass(pid);
+        } catch (Exception ex) {
+            throw new RuntimeException("Test ERROR " + ex, ex);
+        } finally {
+            LingeredApp.stopApp(theApp);
+        }
+        System.out.println("Test PASSED");
+    }
+}
--- a/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java	Thu Nov 30 09:51:28 2017 -0500
@@ -51,7 +51,7 @@
         VM_TYPE("isClient", "isServer", "isGraal", "isMinimal", "isZero", "isEmbedded"),
         MODE("isInt", "isMixed", "isComp"),
         IGNORED("isEmulatedClient", "isDebugBuild", "isFastDebugBuild", "isSlowDebugBuild",
-                "shouldSAAttach", "isTieredSupported");
+                "shouldSAAttach", "isTieredSupported", "areCustomLoadersSupportedForCDS");
 
         public final List<String> methodNames;
 
@@ -106,7 +106,7 @@
                     && m.getReturnType() == boolean.class) {
                 Asserts.assertTrue(allMethods.contains(m.getName()),
                         "All Platform's methods with signature '():Z' should "
-                                + "be tested ");
+                                + "be tested. Missing: " + m.getName());
             }
         }
     }
--- a/test/jtreg-ext/requires/VMProps.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/jtreg-ext/requires/VMProps.java	Thu Nov 30 09:51:28 2017 -0500
@@ -74,6 +74,7 @@
         map.put("vm.aot", vmAOT());
         // vm.cds is true if the VM is compiled with cds support.
         map.put("vm.cds", vmCDS());
+        map.put("vm.cds.custom.loaders", vmCDSForCustomLoaders());
         // vm.graal.enabled is true if Graal is used as JIT
         map.put("vm.graal.enabled", isGraalEnabled());
         map.put("docker.support", dockerSupport());
@@ -297,6 +298,19 @@
     }
 
     /**
+     * Check for CDS support for custom loaders.
+     *
+     * @return true if CDS is supported for customer loader by the VM to be tested.
+     */
+    protected String vmCDSForCustomLoaders() {
+        if (vmCDS().equals("true") && Platform.areCustomLoadersSupportedForCDS()) {
+            return "true";
+        } else {
+            return "false";
+        }
+    }
+
+    /**
      * Check if Graal is used as JIT compiler.
      *
      * @return true if Graal is used as JIT compiler.
--- a/test/lib/jdk/test/lib/Platform.java	Thu Nov 30 09:49:45 2017 -0500
+++ b/test/lib/jdk/test/lib/Platform.java	Thu Nov 30 09:51:28 2017 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -288,4 +288,16 @@
             return "so";
         }
     }
+
+    /*
+     * This should match the #if condition in ClassListParser::load_class_from_source().
+     */
+    public static boolean areCustomLoadersSupportedForCDS() {
+        boolean isLinux = Platform.isLinux();
+        boolean is64 = Platform.is64bit();
+        boolean isSolaris = Platform.isSolaris();
+        boolean isAix = Platform.isAix();
+
+        return (is64 && (isLinux || isSolaris || isAix));
+    }
 }