--- old/src/share/vm/memory/metaspace.hpp 2013-02-20 08:57:03.029692875 +0100 +++ new/src/share/vm/memory/metaspace.hpp 2013-02-20 08:57:02.873692879 +0100 @@ -157,16 +157,16 @@ class MetaspaceAux : AllStatic { + static size_t free_chunks_total(Metaspace::MetadataType mdtype); + static size_t free_chunks_total_in_bytes(Metaspace::MetadataType mdtype); + + public: // Statistics for class space and data space in metaspace. static size_t used_in_bytes(Metaspace::MetadataType mdtype); static size_t free_in_bytes(Metaspace::MetadataType mdtype); static size_t capacity_in_bytes(Metaspace::MetadataType mdtype); static size_t reserved_in_bytes(Metaspace::MetadataType mdtype); - static size_t free_chunks_total(Metaspace::MetadataType mdtype); - static size_t free_chunks_total_in_bytes(Metaspace::MetadataType mdtype); - - public: // Total of space allocated to metadata in all Metaspaces static size_t used_in_bytes() { return used_in_bytes(Metaspace::ClassType) + --- old/src/share/vm/memory/universe.cpp 2013-02-20 08:57:03.897692843 +0100 +++ new/src/share/vm/memory/universe.cpp 2013-02-20 08:57:03.749692848 +0100 @@ -1106,6 +1106,7 @@ // Initialize performance counters for metaspaces MetaspaceCounters::initialize_performance_counters(); + MemoryService::add_metaspace_memory_pools(); GC_locker::unlock(); // allow gc after bootstrapping --- old/src/share/vm/services/memoryManager.cpp 2013-02-20 08:57:04.773692812 +0100 +++ new/src/share/vm/services/memoryManager.cpp 2013-02-20 08:57:04.621692819 +0100 @@ -61,6 +61,10 @@ return (MemoryManager*) new CodeCacheMemoryManager(); } +MemoryManager* MemoryManager::get_metaspace_memory_manager() { + return (MemoryManager*) new MetaspaceMemoryManager(); +} + GCMemoryManager* MemoryManager::get_copy_memory_manager() { return (GCMemoryManager*) new CopyMemoryManager(); } --- old/src/share/vm/services/memoryManager.hpp 2013-02-20 08:57:05.657692781 +0100 +++ new/src/share/vm/services/memoryManager.hpp 2013-02-20 08:57:05.497692787 +0100 @@ -56,6 +56,7 @@ enum Name { Abstract, CodeCache, + Metaspace, Copy, MarkSweepCompact, ParNew, @@ -88,6 +89,7 @@ // Static factory methods to get a memory manager of a specific type static MemoryManager* get_code_cache_memory_manager(); + static MemoryManager* get_metaspace_memory_manager(); static GCMemoryManager* get_copy_memory_manager(); static GCMemoryManager* get_msc_memory_manager(); static GCMemoryManager* get_parnew_memory_manager(); @@ -108,6 +110,14 @@ const char* name() { return "CodeCacheManager"; } }; +class MetaspaceMemoryManager : public MemoryManager { +public: + MetaspaceMemoryManager() : MemoryManager() {} + + MemoryManager::Name kind() { return MemoryManager::Metaspace; } + const char *name() { return "MetaspaceManager"; } +}; + class GCStatInfo : public ResourceObj { private: size_t _index; --- old/src/share/vm/services/memoryPool.cpp 2013-02-20 08:57:06.501692752 +0100 +++ new/src/share/vm/services/memoryPool.cpp 2013-02-20 08:57:06.357692758 +0100 @@ -26,6 +26,7 @@ #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "oops/oop.inline.hpp" +#include "runtime/globals.hpp" #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" #include "services/lowMemoryDetector.hpp" @@ -256,3 +257,37 @@ return MemoryUsage(initial_size(), used, committed, maxSize); } + +MetaspacePoolBase::MetaspacePoolBase(const char *name, + Metaspace::MetadataType md_type, + size_t max_size) : + _md_type(md_type), + MemoryPool(name, NonHeap, MetaspaceAux::capacity_in_bytes(_md_type), max_size, + true, false) { +} + +size_t MetaspacePoolBase::used_in_bytes() { + return MetaspaceAux::used_in_bytes(_md_type); +} + +MemoryUsage MetaspacePoolBase::get_memory_usage() { + size_t used = MetaspaceAux::used_in_bytes(_md_type); + size_t committed = MetaspaceAux::capacity_in_bytes(_md_type); + return MemoryUsage(initial_size(), used, committed, max_size()); +} + +ClassMetaspacePool::ClassMetaspacePool() : + MetaspacePoolBase("Class Metaspace", Metaspace::ClassType, calculate_max_size()) { +} + +size_t ClassMetaspacePool::calculate_max_size() { + return UseCompressedKlassPointers ? ClassMetaspaceSize : _undefined_max_size; +} + +MetaspacePool::MetaspacePool() : + MetaspacePoolBase("Metaspace", Metaspace::NonClassType, calculate_max_size()) { +} + +size_t MetaspacePool::calculate_max_size() { + return FLAG_IS_CMDLINE(MaxMetaspaceSize) ? MaxMetaspaceSize : _undefined_max_size; +} --- old/src/share/vm/services/memoryPool.hpp 2013-02-20 08:57:07.301692724 +0100 +++ new/src/share/vm/services/memoryPool.hpp 2013-02-20 08:57:07.153692730 +0100 @@ -28,6 +28,7 @@ #include "gc_implementation/shared/mutableSpace.hpp" #include "memory/defNewGeneration.hpp" #include "memory/heap.hpp" +#include "memory/metaspace.hpp" #include "memory/space.hpp" #include "services/memoryUsage.hpp" #include "utilities/macros.hpp" @@ -222,4 +223,29 @@ size_t used_in_bytes() { return _codeHeap->allocated_capacity(); } }; +class MetaspacePoolBase : public MemoryPool { +private: + Metaspace::MetadataType _md_type; +protected: + static const size_t _undefined_max_size = (size_t) -1; +public: + MetaspacePoolBase(const char *name, Metaspace::MetadataType md_type, size_t max_size); + MemoryUsage get_memory_usage(); + size_t used_in_bytes(); +}; + +class ClassMetaspacePool : public MetaspacePoolBase { +private: + size_t calculate_max_size(); +public: + ClassMetaspacePool(); +}; + +class MetaspacePool : public MetaspacePoolBase { +private: + size_t calculate_max_size(); +public: + MetaspacePool(); +}; + #endif // SHARE_VM_SERVICES_MEMORYPOOL_HPP --- old/src/share/vm/services/memoryService.cpp 2013-02-20 08:57:08.213692691 +0100 +++ new/src/share/vm/services/memoryService.cpp 2013-02-20 08:57:08.049692697 +0100 @@ -60,9 +60,11 @@ GrowableArray* MemoryService::_managers_list = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(init_managers_list_size, true); -GCMemoryManager* MemoryService::_minor_gc_manager = NULL; -GCMemoryManager* MemoryService::_major_gc_manager = NULL; -MemoryPool* MemoryService::_code_heap_pool = NULL; +GCMemoryManager* MemoryService::_minor_gc_manager = NULL; +GCMemoryManager* MemoryService::_major_gc_manager = NULL; +MemoryPool* MemoryService::_code_heap_pool = NULL; +MemoryPool* MemoryService::_metaspace_pool = NULL; +MemoryPool* MemoryService::_class_metaspace_pool = NULL; class GcThreadCountClosure: public ThreadClosure { private: @@ -398,6 +400,19 @@ _managers_list->append(mgr); } +void MemoryService::add_metaspace_memory_pools() { + _metaspace_pool = new MetaspacePool(); + _class_metaspace_pool = new ClassMetaspacePool(); + + MemoryManager* mgr = MemoryManager::get_metaspace_memory_manager(); + mgr->add_pool(_metaspace_pool); + mgr->add_pool(_class_metaspace_pool); + + _pools_list->append(_metaspace_pool); + _pools_list->append(_class_metaspace_pool); + _managers_list->append(mgr); +} + MemoryManager* MemoryService::get_memory_manager(instanceHandle mh) { for (int i = 0; i < _managers_list->length(); i++) { MemoryManager* mgr = _managers_list->at(i); --- old/src/share/vm/services/memoryService.hpp 2013-02-20 08:57:09.021692663 +0100 +++ new/src/share/vm/services/memoryService.hpp 2013-02-20 08:57:08.877692668 +0100 @@ -73,6 +73,10 @@ // Code heap memory pool static MemoryPool* _code_heap_pool; + // Metaspace pools + static MemoryPool* _metaspace_pool; + static MemoryPool* _class_metaspace_pool; + static void add_generation_memory_pool(Generation* gen, MemoryManager* major_mgr, MemoryManager* minor_mgr); @@ -121,6 +125,7 @@ public: static void set_universe_heap(CollectedHeap* heap); static void add_code_heap_memory_pool(CodeHeap* heap); + static void add_metaspace_memory_pools(); static MemoryPool* get_memory_pool(instanceHandle pool); static MemoryManager* get_memory_manager(instanceHandle mgr); --- /dev/null 2013-02-19 18:27:51.183525753 +0100 +++ new/test/gc/metaspace/TestMetaspaceMemoryPools.java 2013-02-20 08:57:09.665692640 +0100 @@ -0,0 +1,75 @@ +import java.util.List; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryManagerMXBean; +import java.lang.management.MemoryPoolMXBean; +import java.lang.management.MemoryUsage; + +/* @test TestMetaspaceMemoryPools + * @bug 8000754 + * @summary Tests that two MemoryPoolMXBeans, one for metaspace and one for + * class metaspace, is created and that a MemoryManagerMXBean is + * created. + * @run main/othervm TestMetaspaceMemoryPools defined undefined + * @run main/othervm -XX:-UseCompressedKlassPointers TestMetaspaceMemoryPools undefined undefined + * @run main/othervm -XX:-UseCompressedKlassPointers -XX:MaxMetaspaceSize=60m TestMetaspaceMemoryPools undefined defined + */ +public class TestMetaspaceMemoryPools { + public static void main(String[] args) { + boolean isClassMetaspaceMaxDefined = args[0].equals("defined"); + boolean isMetaspaceMaxDefined = args[1].equals("defined"); + + verifyThatMetaspaceMemoryManagerExists(); + + verifyMemoryPool(getMemoryPool("Class Metaspace"), isClassMetaspaceMaxDefined); + verifyMemoryPool(getMemoryPool("Metaspace"), isMetaspaceMaxDefined); + } + + private static void verifyThatMetaspaceMemoryManagerExists() { + List managers = ManagementFactory.getMemoryManagerMXBeans(); + for (MemoryManagerMXBean manager : managers) { + if (manager.getName().equals("MetaspaceManager")) { + return; + } + } + + throw new RuntimeException("Expected to find a metaspace memory manager"); + } + + private static MemoryPoolMXBean getMemoryPool(String name) { + List pools = ManagementFactory.getMemoryPoolMXBeans(); + for (MemoryPoolMXBean pool : pools) { + if (pool.getName().equals(name)) { + return pool; + } + } + + throw new RuntimeException("Expected to find a memory pool with name " + name); + } + + private static void verifyMemoryPool(MemoryPoolMXBean pool, boolean isMaxDefined) { + MemoryUsage mu = pool.getUsage(); + assertDefined(mu.getInit(), "init"); + assertDefined(mu.getUsed(), "used"); + assertDefined(mu.getCommitted(), "committed"); + + if (isMaxDefined) { + assertDefined(mu.getMax(), "max"); + } else { + assertUndefined(mu.getMax(), "max"); + } + } + + private static void assertDefined(long value, String name) { + assertTrue(value != -1, "Expected " + name + " to be defined"); + } + + private static void assertUndefined(long value, String name) { + assertTrue(value == -1, "Expected " + name + " to be undefined"); + } + + private static void assertTrue(boolean condition, String msg) { + if (!condition) { + throw new RuntimeException(msg); + } + } +}