diff a/src/hotspot/share/memory/classLoaderMetaspace.cpp b/src/hotspot/share/memory/classLoaderMetaspace.cpp
--- a/src/hotspot/share/memory/classLoaderMetaspace.cpp
+++ b/src/hotspot/share/memory/classLoaderMetaspace.cpp
@@ -28,53 +28,64 @@
 #include "memory/classLoaderMetaspace.hpp"
 #include "memory/metaspace.hpp"
 #include "memory/metaspaceUtils.hpp"
 #include "memory/metaspace/chunkManager.hpp"
 #include "memory/metaspace/internalStats.hpp"
+#include "memory/metaspace/metablock.hpp"
 #include "memory/metaspace/metaspaceArena.hpp"
 #include "memory/metaspace/metaspaceArenaGrowthPolicy.hpp"
+#include "memory/metaspace/metaspaceCommon.hpp"
+#include "memory/metaspace/metaspaceContext.hpp"
 #include "memory/metaspace/metaspaceSettings.hpp"
 #include "memory/metaspace/metaspaceStatistics.hpp"
 #include "memory/metaspace/runningCounters.hpp"
 #include "memory/metaspaceTracer.hpp"
+#include "oops/klass.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "utilities/debug.hpp"
 
 using metaspace::ChunkManager;
+using metaspace::MetaBlock;
 using metaspace::MetaspaceArena;
+using metaspace::MetaspaceContext;
 using metaspace::ArenaGrowthPolicy;
 using metaspace::RunningCounters;
 using metaspace::InternalStats;
 
 #define LOGFMT         "CLMS @" PTR_FORMAT " "
 #define LOGFMT_ARGS    p2i(this)
 
 ClassLoaderMetaspace::ClassLoaderMetaspace(Mutex* lock, Metaspace::MetaspaceType space_type) :
+    ClassLoaderMetaspace(lock, space_type,
+                         MetaspaceContext::context_nonclass(),
+                         MetaspaceContext::context_class(),
+                         CompressedKlassPointers::klass_alignment_in_words())
+{}
+
+ClassLoaderMetaspace::ClassLoaderMetaspace(Mutex* lock, Metaspace::MetaspaceType space_type,
+                                           MetaspaceContext* non_class_context,
+                                           MetaspaceContext* class_context,
+                                           size_t klass_alignment_words) :
   _lock(lock),
   _space_type(space_type),
   _non_class_space_arena(nullptr),
   _class_space_arena(nullptr)
 {
-  ChunkManager* const non_class_cm =
-          ChunkManager::chunkmanager_nonclass();
-
   // Initialize non-class Arena
   _non_class_space_arena = new MetaspaceArena(
-      non_class_cm,
+      non_class_context,
       ArenaGrowthPolicy::policy_for_space_type(space_type, false),
-      RunningCounters::used_nonclass_counter(),
-      "non-class sm");
+      Metaspace::min_allocation_alignment_words,
+      "non-class arena");
 
   // If needed, initialize class arena
-  if (Metaspace::using_class_space()) {
-    ChunkManager* const class_cm =
-            ChunkManager::chunkmanager_class();
+  if (class_context != nullptr) {
     _class_space_arena = new MetaspaceArena(
-        class_cm,
+        class_context,
         ArenaGrowthPolicy::policy_for_space_type(space_type, true),
-        RunningCounters::used_class_counter(),
-        "class sm");
+        klass_alignment_words,
+        "class arena");
   }
 
   UL2(debug, "born (nonclass arena: " PTR_FORMAT ", class arena: " PTR_FORMAT ".",
       p2i(_non_class_space_arena), p2i(_class_space_arena));
 }
@@ -87,16 +98,32 @@
 
 }
 
 // Allocate word_size words from Metaspace.
 MetaWord* ClassLoaderMetaspace::allocate(size_t word_size, Metaspace::MetadataType mdType) {
+  word_size = align_up(word_size, Metaspace::min_allocation_word_size);
   MutexLocker fcl(lock(), Mutex::_no_safepoint_check_flag);
-  if (Metaspace::is_class_space_allocation(mdType)) {
-    return class_space_arena()->allocate(word_size);
+  MetaBlock result, wastage;
+  const bool is_class = have_class_space_arena() && mdType == Metaspace::ClassType;
+  if (is_class) {
+    assert(word_size >= (sizeof(Klass)/BytesPerWord), "weird size for klass: %zu", word_size);
+    result = class_space_arena()->allocate(word_size, wastage);
   } else {
-    return non_class_space_arena()->allocate(word_size);
+    result = non_class_space_arena()->allocate(word_size, wastage);
+  }
+  if (wastage.is_nonempty()) {
+    non_class_space_arena()->deallocate(wastage);
+  }
+#ifdef ASSERT
+  if (result.is_nonempty()) {
+    const bool in_class_arena = class_space_arena() != nullptr ? class_space_arena()->contains(result) : false;
+    const bool in_nonclass_arena = non_class_space_arena()->contains(result);
+    assert((is_class && in_class_arena) || (!is_class && in_class_arena != in_nonclass_arena),
+           "block from neither arena " METABLOCKFORMAT "?", METABLOCKFORMATARGS(result));
   }
+#endif
+  return result.base();
 }
 
 // Attempt to expand the GC threshold to be good for at least another word_size words
 // and allocate. Returns null if failure. Used during Metaspace GC.
 MetaWord* ClassLoaderMetaspace::expand_and_allocate(size_t word_size, Metaspace::MetadataType mdType) {
@@ -129,17 +156,23 @@
 }
 
 // Prematurely returns a metaspace allocation to the _block_freelists
 // because it is not needed anymore.
 void ClassLoaderMetaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) {
-  MutexLocker fcl(lock(), Mutex::_no_safepoint_check_flag);
-  if (Metaspace::using_class_space() && is_class) {
-    class_space_arena()->deallocate(ptr, word_size);
-  } else {
-    non_class_space_arena()->deallocate(ptr, word_size);
+  NOT_LP64(word_size = align_down(word_size, Metaspace::min_allocation_word_size);)
+  MetaBlock bl(ptr, word_size);
+  if (word_size >= Metaspace::min_allocation_word_size) {
+    MutexLocker fcl(lock(), Mutex::_no_safepoint_check_flag);
+    if (have_class_space_arena() && is_class) {
+      assert(class_space_arena()->contains(bl),
+             "Not from class arena " METABLOCKFORMAT "?", METABLOCKFORMATARGS(bl));
+      class_space_arena()->deallocate(MetaBlock(ptr, word_size));
+    } else {
+      non_class_space_arena()->deallocate(MetaBlock(ptr, word_size));
+    }
+    DEBUG_ONLY(InternalStats::inc_num_deallocs();)
   }
-  DEBUG_ONLY(InternalStats::inc_num_deallocs();)
 }
 
 // Update statistics. This walks all in-use chunks.
 void ClassLoaderMetaspace::add_to_statistics(metaspace::ClmsStats* out) const {
   MutexLocker fcl(lock(), Mutex::_no_safepoint_check_flag);
@@ -177,11 +210,11 @@
   size_t used_nc, comm_nc, cap_nc;
   size_t used_c = 0, comm_c = 0, cap_c = 0;
   {
     MutexLocker fcl(lock(), Mutex::_no_safepoint_check_flag);
     usage_numbers(Metaspace::MetadataType::NonClassType, &used_nc, &comm_nc, &cap_nc);
-    if (Metaspace::using_class_space()) {
+    if (have_class_space_arena()) {
       usage_numbers(Metaspace::MetadataType::ClassType, &used_c, &comm_c, &cap_c);
     }
   }
   if (p_used_words != nullptr) {
     (*p_used_words) = used_nc + used_c;
