# HG changeset patch # User tschatzl # Date 1536056315 -7200 # Node ID c265860d5d456bffe213e97f4c67b07e7139ea85 # Parent 7ed777a140944306cab8bb8a57df46ed63b684ca 8207200: Committed > max memory usage when getting MemoryUsage Summary: Make sure that modification of memory usage variables are synchronized with returning them to Java. Reviewed-by: sangheki, mchung diff -r 7ed777a14094 -r c265860d5d45 src/hotspot/share/gc/g1/g1CollectedHeap.cpp --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Tue Sep 04 12:17:23 2018 +0200 +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Tue Sep 04 12:18:35 2018 +0200 @@ -4654,6 +4654,10 @@ _g1mm->initialize_serviceability(); } +MemoryUsage G1CollectedHeap::memory_usage() { + return _g1mm->memory_usage(); +} + GrowableArray G1CollectedHeap::memory_managers() { return _g1mm->memory_managers(); } diff -r 7ed777a14094 -r c265860d5d45 src/hotspot/share/gc/g1/g1CollectedHeap.hpp --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Tue Sep 04 12:17:23 2018 +0200 +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Tue Sep 04 12:18:35 2018 +0200 @@ -961,6 +961,7 @@ virtual SoftRefPolicy* soft_ref_policy(); virtual void initialize_serviceability(); + virtual MemoryUsage memory_usage(); virtual GrowableArray memory_managers(); virtual GrowableArray memory_pools(); diff -r 7ed777a14094 -r c265860d5d45 src/hotspot/share/gc/g1/g1MemoryPool.cpp --- a/src/hotspot/share/gc/g1/g1MemoryPool.cpp Tue Sep 04 12:17:23 2018 +0200 +++ b/src/hotspot/share/gc/g1/g1MemoryPool.cpp Tue Sep 04 12:18:35 2018 +0200 @@ -48,9 +48,7 @@ false /* support_usage_threshold */) { } MemoryUsage G1EdenPool::get_memory_usage() { - size_t committed = _g1mm->eden_space_committed(); - - return MemoryUsage(initial_size(), used_in_bytes(), committed, max_size()); + return _g1mm->eden_space_memory_usage(initial_size(), max_size()); } G1SurvivorPool::G1SurvivorPool(G1CollectedHeap* g1h, size_t initial_size) : @@ -61,9 +59,7 @@ false /* support_usage_threshold */) { } MemoryUsage G1SurvivorPool::get_memory_usage() { - size_t committed = _g1mm->survivor_space_committed(); - - return MemoryUsage(initial_size(), used_in_bytes(), committed, max_size()); + return _g1mm->survivor_space_memory_usage(initial_size(), max_size()); } G1OldGenPool::G1OldGenPool(G1CollectedHeap* g1h, size_t initial_size, size_t max_size) : @@ -74,7 +70,5 @@ true /* support_usage_threshold */) { } MemoryUsage G1OldGenPool::get_memory_usage() { - size_t committed = _g1mm->old_gen_committed(); - - return MemoryUsage(initial_size(), used_in_bytes(), committed, max_size()); + return _g1mm->old_gen_memory_usage(initial_size(), max_size()); } diff -r 7ed777a14094 -r c265860d5d45 src/hotspot/share/gc/g1/g1MonitoringSupport.cpp --- a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp Tue Sep 04 12:17:23 2018 +0200 +++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp Tue Sep 04 12:18:35 2018 +0200 @@ -202,6 +202,11 @@ _incremental_memory_manager.add_pool(_old_gen_pool, false /* always_affected_by_gc */); } +MemoryUsage G1MonitoringSupport::memory_usage() { + MutexLockerEx x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag); + return MemoryUsage(InitialHeapSize, _overall_used, _overall_committed, _g1h->max_capacity()); +} + GrowableArray G1MonitoringSupport::memory_managers() { GrowableArray memory_managers(2); memory_managers.append(&_incremental_memory_manager); @@ -220,6 +225,7 @@ void G1MonitoringSupport::recalculate_sizes() { assert_heap_locked_or_at_safepoint(true); + MutexLockerEx x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag); // Recalculate all the sizes from scratch. uint young_list_length = _g1h->young_regions_count(); @@ -296,13 +302,41 @@ } void G1MonitoringSupport::update_eden_size() { - // Recalculate everything - this is fast enough. + // Recalculate everything - this should be fast enough and we are sure that we do not + // miss anything. recalculate_sizes(); if (UsePerfData) { _eden_space_counters->update_used(_eden_space_used); } } +MemoryUsage G1MonitoringSupport::eden_space_memory_usage(size_t initial_size, size_t max_size) { + MutexLockerEx x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag); + + return MemoryUsage(initial_size, + _eden_space_used, + _eden_space_committed, + max_size); +} + +MemoryUsage G1MonitoringSupport::survivor_space_memory_usage(size_t initial_size, size_t max_size) { + MutexLockerEx x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag); + + return MemoryUsage(initial_size, + _survivor_space_used, + _survivor_space_committed, + max_size); +} + +MemoryUsage G1MonitoringSupport::old_gen_memory_usage(size_t initial_size, size_t max_size) { + MutexLockerEx x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag); + + return MemoryUsage(initial_size, + _old_gen_used, + _old_gen_committed, + max_size); +} + G1MonitoringScope::G1MonitoringScope(G1MonitoringSupport* g1mm, bool full_gc, bool all_memory_pools_affected) : _tcs(full_gc ? g1mm->_full_collection_counters : g1mm->_incremental_collection_counters), _tms(full_gc ? &g1mm->_full_gc_memory_manager : &g1mm->_incremental_memory_manager, diff -r 7ed777a14094 -r c265860d5d45 src/hotspot/share/gc/g1/g1MonitoringSupport.hpp --- a/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp Tue Sep 04 12:17:23 2018 +0200 +++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp Tue Sep 04 12:18:35 2018 +0200 @@ -29,6 +29,7 @@ #include "gc/shared/generationCounters.hpp" #include "services/memoryManager.hpp" #include "services/memoryService.hpp" +#include "runtime/mutex.hpp" class CollectorCounters; class G1CollectedHeap; @@ -198,6 +199,8 @@ ~G1MonitoringSupport(); void initialize_serviceability(); + + MemoryUsage memory_usage(); GrowableArray memory_managers(); GrowableArray memory_pools(); @@ -230,16 +233,22 @@ // MemoryService // jstat counters // Tracing + // Values may not be consistent wrt to each other. size_t young_gen_committed() { return _young_gen_committed; } - size_t eden_space_committed() { return _eden_space_committed; } size_t eden_space_used() { return _eden_space_used; } - size_t survivor_space_committed() { return _survivor_space_committed; } size_t survivor_space_used() { return _survivor_space_used; } size_t old_gen_committed() { return _old_gen_committed; } size_t old_gen_used() { return _old_gen_used; } + + // Monitoring support for MemoryPools. Values in the returned MemoryUsage are + // guaranteed to be consistent with each other. + MemoryUsage eden_space_memory_usage(size_t initial_size, size_t max_size); + MemoryUsage survivor_space_memory_usage(size_t initial_size, size_t max_size); + + MemoryUsage old_gen_memory_usage(size_t initial_size, size_t max_size); }; // Scope object for java.lang.management support. diff -r 7ed777a14094 -r c265860d5d45 src/hotspot/share/gc/shared/collectedHeap.cpp --- a/src/hotspot/share/gc/shared/collectedHeap.cpp Tue Sep 04 12:17:23 2018 +0200 +++ b/src/hotspot/share/gc/shared/collectedHeap.cpp Tue Sep 04 12:18:35 2018 +0200 @@ -328,6 +328,11 @@ } while (true); // Until a GC is done } +MemoryUsage CollectedHeap::memory_usage() { + return MemoryUsage(InitialHeapSize, used(), capacity(), max_capacity()); +} + + #ifndef PRODUCT void CollectedHeap::check_for_non_bad_heap_word_value(HeapWord* addr, size_t size) { if (CheckMemoryInitialization && ZapUnusedHeapArea) { diff -r 7ed777a14094 -r c265860d5d45 src/hotspot/share/gc/shared/collectedHeap.hpp --- a/src/hotspot/share/gc/shared/collectedHeap.hpp Tue Sep 04 12:17:23 2018 +0200 +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp Tue Sep 04 12:18:35 2018 +0200 @@ -31,6 +31,7 @@ #include "runtime/handles.hpp" #include "runtime/perfData.hpp" #include "runtime/safepoint.hpp" +#include "services/memoryUsage.hpp" #include "utilities/debug.hpp" #include "utilities/events.hpp" #include "utilities/formatBuffer.hpp" @@ -423,6 +424,7 @@ // Return the SoftRefPolicy for the heap; virtual SoftRefPolicy* soft_ref_policy() = 0; + virtual MemoryUsage memory_usage(); virtual GrowableArray memory_managers() = 0; virtual GrowableArray memory_pools() = 0; diff -r 7ed777a14094 -r c265860d5d45 src/hotspot/share/runtime/mutexLocker.cpp --- a/src/hotspot/share/runtime/mutexLocker.cpp Tue Sep 04 12:17:23 2018 +0200 +++ b/src/hotspot/share/runtime/mutexLocker.cpp Tue Sep 04 12:18:35 2018 +0200 @@ -88,6 +88,7 @@ Mutex* Shared_DirtyCardQ_lock = NULL; Mutex* MarkStackFreeList_lock = NULL; Mutex* MarkStackChunkList_lock = NULL; +Mutex* MonitoringSupport_lock = NULL; Mutex* ParGCRareEvent_lock = NULL; Mutex* DerivedPointerTableGC_lock = NULL; Monitor* CGCPhaseManager_lock = NULL; @@ -216,6 +217,8 @@ def(MarkStackFreeList_lock , PaddedMutex , leaf , true, Monitor::_safepoint_check_never); def(MarkStackChunkList_lock , PaddedMutex , leaf , true, Monitor::_safepoint_check_never); + + def(MonitoringSupport_lock , PaddedMutex , native , true, Monitor::_safepoint_check_never); // used for serviceability monitoring support } def(ParGCRareEvent_lock , PaddedMutex , leaf , true, Monitor::_safepoint_check_sometimes); def(DerivedPointerTableGC_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_never); diff -r 7ed777a14094 -r c265860d5d45 src/hotspot/share/runtime/mutexLocker.hpp --- a/src/hotspot/share/runtime/mutexLocker.hpp Tue Sep 04 12:17:23 2018 +0200 +++ b/src/hotspot/share/runtime/mutexLocker.hpp Tue Sep 04 12:18:35 2018 +0200 @@ -94,6 +94,7 @@ // non-Java threads. extern Mutex* MarkStackFreeList_lock; // Protects access to the global mark stack free list. extern Mutex* MarkStackChunkList_lock; // Protects access to the global mark stack chunk list. +extern Mutex* MonitoringSupport_lock; // Protects updates to the serviceability memory pools. extern Mutex* ParGCRareEvent_lock; // Synchronizes various (rare) parallel GC ops. extern Mutex* Compile_lock; // a lock held when Compilation is updating code (used to block CodeCache traversal, CHA updates, etc) extern Monitor* MethodCompileQueue_lock; // a lock held when method compilations are enqueued, dequeued diff -r 7ed777a14094 -r c265860d5d45 src/hotspot/share/services/management.cpp --- a/src/hotspot/share/services/management.cpp Tue Sep 04 12:17:23 2018 +0200 +++ b/src/hotspot/share/services/management.cpp Tue Sep 04 12:18:35 2018 +0200 @@ -713,50 +713,53 @@ JVM_ENTRY(jobject, jmm_GetMemoryUsage(JNIEnv* env, jboolean heap)) ResourceMark rm(THREAD); - // Calculate the memory usage - size_t total_init = 0; - size_t total_used = 0; - size_t total_committed = 0; - size_t total_max = 0; - bool has_undefined_init_size = false; - bool has_undefined_max_size = false; + MemoryUsage usage; + + if (heap) { + usage = Universe::heap()->memory_usage(); + } else { + // Calculate the memory usage by summing up the pools. + size_t total_init = 0; + size_t total_used = 0; + size_t total_committed = 0; + size_t total_max = 0; + bool has_undefined_init_size = false; + bool has_undefined_max_size = false; - for (int i = 0; i < MemoryService::num_memory_pools(); i++) { - MemoryPool* pool = MemoryService::get_memory_pool(i); - if ((heap && pool->is_heap()) || (!heap && pool->is_non_heap())) { - MemoryUsage u = pool->get_memory_usage(); - total_used += u.used(); - total_committed += u.committed(); + for (int i = 0; i < MemoryService::num_memory_pools(); i++) { + MemoryPool* pool = MemoryService::get_memory_pool(i); + if (pool->is_non_heap()) { + MemoryUsage u = pool->get_memory_usage(); + total_used += u.used(); + total_committed += u.committed(); - if (u.init_size() == (size_t)-1) { - has_undefined_init_size = true; - } - if (!has_undefined_init_size) { - total_init += u.init_size(); - } + if (u.init_size() == MemoryUsage::undefined_size()) { + has_undefined_init_size = true; + } + if (!has_undefined_init_size) { + total_init += u.init_size(); + } - if (u.max_size() == (size_t)-1) { - has_undefined_max_size = true; - } - if (!has_undefined_max_size) { - total_max += u.max_size(); + if (u.max_size() == MemoryUsage::undefined_size()) { + has_undefined_max_size = true; + } + if (!has_undefined_max_size) { + total_max += u.max_size(); + } } } - } - // if any one of the memory pool has undefined init_size or max_size, - // set it to -1 - if (has_undefined_init_size) { - total_init = (size_t)-1; + // if any one of the memory pool has undefined init_size or max_size, + // set it to MemoryUsage::undefined_size() + if (has_undefined_init_size) { + total_init = MemoryUsage::undefined_size(); + } + if (has_undefined_max_size) { + total_max = MemoryUsage::undefined_size(); + } + + usage = MemoryUsage(total_init, total_used, total_committed, total_max); } - if (has_undefined_max_size) { - total_max = (size_t)-1; - } - - MemoryUsage usage((heap ? InitialHeapSize : total_init), - total_used, - total_committed, - (heap ? Universe::heap()->max_capacity() : total_max)); Handle obj = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL); return JNIHandles::make_local(env, obj());