mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8207200: Committed > max memory usage when getting MemoryUsage
Make sure that modification of memory usage variables are synchronized with returning them to Java. Reviewed-by: sangheki, mchung
This commit is contained in:
parent
a7d4df53fa
commit
db7b4e20e1
10 changed files with 105 additions and 49 deletions
|
@ -4654,6 +4654,10 @@ void G1CollectedHeap::initialize_serviceability() {
|
||||||
_g1mm->initialize_serviceability();
|
_g1mm->initialize_serviceability();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MemoryUsage G1CollectedHeap::memory_usage() {
|
||||||
|
return _g1mm->memory_usage();
|
||||||
|
}
|
||||||
|
|
||||||
GrowableArray<GCMemoryManager*> G1CollectedHeap::memory_managers() {
|
GrowableArray<GCMemoryManager*> G1CollectedHeap::memory_managers() {
|
||||||
return _g1mm->memory_managers();
|
return _g1mm->memory_managers();
|
||||||
}
|
}
|
||||||
|
|
|
@ -961,6 +961,7 @@ public:
|
||||||
virtual SoftRefPolicy* soft_ref_policy();
|
virtual SoftRefPolicy* soft_ref_policy();
|
||||||
|
|
||||||
virtual void initialize_serviceability();
|
virtual void initialize_serviceability();
|
||||||
|
virtual MemoryUsage memory_usage();
|
||||||
virtual GrowableArray<GCMemoryManager*> memory_managers();
|
virtual GrowableArray<GCMemoryManager*> memory_managers();
|
||||||
virtual GrowableArray<MemoryPool*> memory_pools();
|
virtual GrowableArray<MemoryPool*> memory_pools();
|
||||||
|
|
||||||
|
|
|
@ -48,9 +48,7 @@ G1EdenPool::G1EdenPool(G1CollectedHeap* g1h, size_t initial_size) :
|
||||||
false /* support_usage_threshold */) { }
|
false /* support_usage_threshold */) { }
|
||||||
|
|
||||||
MemoryUsage G1EdenPool::get_memory_usage() {
|
MemoryUsage G1EdenPool::get_memory_usage() {
|
||||||
size_t committed = _g1mm->eden_space_committed();
|
return _g1mm->eden_space_memory_usage(initial_size(), max_size());
|
||||||
|
|
||||||
return MemoryUsage(initial_size(), used_in_bytes(), committed, max_size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
G1SurvivorPool::G1SurvivorPool(G1CollectedHeap* g1h, size_t initial_size) :
|
G1SurvivorPool::G1SurvivorPool(G1CollectedHeap* g1h, size_t initial_size) :
|
||||||
|
@ -61,9 +59,7 @@ G1SurvivorPool::G1SurvivorPool(G1CollectedHeap* g1h, size_t initial_size) :
|
||||||
false /* support_usage_threshold */) { }
|
false /* support_usage_threshold */) { }
|
||||||
|
|
||||||
MemoryUsage G1SurvivorPool::get_memory_usage() {
|
MemoryUsage G1SurvivorPool::get_memory_usage() {
|
||||||
size_t committed = _g1mm->survivor_space_committed();
|
return _g1mm->survivor_space_memory_usage(initial_size(), max_size());
|
||||||
|
|
||||||
return MemoryUsage(initial_size(), used_in_bytes(), committed, max_size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
G1OldGenPool::G1OldGenPool(G1CollectedHeap* g1h, size_t initial_size, size_t max_size) :
|
G1OldGenPool::G1OldGenPool(G1CollectedHeap* g1h, size_t initial_size, size_t max_size) :
|
||||||
|
@ -74,7 +70,5 @@ G1OldGenPool::G1OldGenPool(G1CollectedHeap* g1h, size_t initial_size, size_t max
|
||||||
true /* support_usage_threshold */) { }
|
true /* support_usage_threshold */) { }
|
||||||
|
|
||||||
MemoryUsage G1OldGenPool::get_memory_usage() {
|
MemoryUsage G1OldGenPool::get_memory_usage() {
|
||||||
size_t committed = _g1mm->old_gen_committed();
|
return _g1mm->old_gen_memory_usage(initial_size(), max_size());
|
||||||
|
|
||||||
return MemoryUsage(initial_size(), used_in_bytes(), committed, max_size());
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,6 +202,11 @@ void G1MonitoringSupport::initialize_serviceability() {
|
||||||
_incremental_memory_manager.add_pool(_old_gen_pool, false /* always_affected_by_gc */);
|
_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<GCMemoryManager*> G1MonitoringSupport::memory_managers() {
|
GrowableArray<GCMemoryManager*> G1MonitoringSupport::memory_managers() {
|
||||||
GrowableArray<GCMemoryManager*> memory_managers(2);
|
GrowableArray<GCMemoryManager*> memory_managers(2);
|
||||||
memory_managers.append(&_incremental_memory_manager);
|
memory_managers.append(&_incremental_memory_manager);
|
||||||
|
@ -220,6 +225,7 @@ GrowableArray<MemoryPool*> G1MonitoringSupport::memory_pools() {
|
||||||
void G1MonitoringSupport::recalculate_sizes() {
|
void G1MonitoringSupport::recalculate_sizes() {
|
||||||
assert_heap_locked_or_at_safepoint(true);
|
assert_heap_locked_or_at_safepoint(true);
|
||||||
|
|
||||||
|
MutexLockerEx x(MonitoringSupport_lock, Mutex::_no_safepoint_check_flag);
|
||||||
// Recalculate all the sizes from scratch.
|
// Recalculate all the sizes from scratch.
|
||||||
|
|
||||||
uint young_list_length = _g1h->young_regions_count();
|
uint young_list_length = _g1h->young_regions_count();
|
||||||
|
@ -296,13 +302,41 @@ void G1MonitoringSupport::update_sizes() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1MonitoringSupport::update_eden_size() {
|
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();
|
recalculate_sizes();
|
||||||
if (UsePerfData) {
|
if (UsePerfData) {
|
||||||
_eden_space_counters->update_used(_eden_space_used);
|
_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) :
|
G1MonitoringScope::G1MonitoringScope(G1MonitoringSupport* g1mm, bool full_gc, bool all_memory_pools_affected) :
|
||||||
_tcs(full_gc ? g1mm->_full_collection_counters : g1mm->_incremental_collection_counters),
|
_tcs(full_gc ? g1mm->_full_collection_counters : g1mm->_incremental_collection_counters),
|
||||||
_tms(full_gc ? &g1mm->_full_gc_memory_manager : &g1mm->_incremental_memory_manager,
|
_tms(full_gc ? &g1mm->_full_gc_memory_manager : &g1mm->_incremental_memory_manager,
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "gc/shared/generationCounters.hpp"
|
#include "gc/shared/generationCounters.hpp"
|
||||||
#include "services/memoryManager.hpp"
|
#include "services/memoryManager.hpp"
|
||||||
#include "services/memoryService.hpp"
|
#include "services/memoryService.hpp"
|
||||||
|
#include "runtime/mutex.hpp"
|
||||||
|
|
||||||
class CollectorCounters;
|
class CollectorCounters;
|
||||||
class G1CollectedHeap;
|
class G1CollectedHeap;
|
||||||
|
@ -198,6 +199,8 @@ public:
|
||||||
~G1MonitoringSupport();
|
~G1MonitoringSupport();
|
||||||
|
|
||||||
void initialize_serviceability();
|
void initialize_serviceability();
|
||||||
|
|
||||||
|
MemoryUsage memory_usage();
|
||||||
GrowableArray<GCMemoryManager*> memory_managers();
|
GrowableArray<GCMemoryManager*> memory_managers();
|
||||||
GrowableArray<MemoryPool*> memory_pools();
|
GrowableArray<MemoryPool*> memory_pools();
|
||||||
|
|
||||||
|
@ -230,16 +233,22 @@ public:
|
||||||
// MemoryService
|
// MemoryService
|
||||||
// jstat counters
|
// jstat counters
|
||||||
// Tracing
|
// Tracing
|
||||||
|
// Values may not be consistent wrt to each other.
|
||||||
|
|
||||||
size_t young_gen_committed() { return _young_gen_committed; }
|
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 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 survivor_space_used() { return _survivor_space_used; }
|
||||||
|
|
||||||
size_t old_gen_committed() { return _old_gen_committed; }
|
size_t old_gen_committed() { return _old_gen_committed; }
|
||||||
size_t old_gen_used() { return _old_gen_used; }
|
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.
|
// Scope object for java.lang.management support.
|
||||||
|
|
|
@ -328,6 +328,11 @@ MetaWord* CollectedHeap::satisfy_failed_metadata_allocation(ClassLoaderData* loa
|
||||||
} while (true); // Until a GC is done
|
} while (true); // Until a GC is done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MemoryUsage CollectedHeap::memory_usage() {
|
||||||
|
return MemoryUsage(InitialHeapSize, used(), capacity(), max_capacity());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
void CollectedHeap::check_for_non_bad_heap_word_value(HeapWord* addr, size_t size) {
|
void CollectedHeap::check_for_non_bad_heap_word_value(HeapWord* addr, size_t size) {
|
||||||
if (CheckMemoryInitialization && ZapUnusedHeapArea) {
|
if (CheckMemoryInitialization && ZapUnusedHeapArea) {
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "runtime/handles.hpp"
|
#include "runtime/handles.hpp"
|
||||||
#include "runtime/perfData.hpp"
|
#include "runtime/perfData.hpp"
|
||||||
#include "runtime/safepoint.hpp"
|
#include "runtime/safepoint.hpp"
|
||||||
|
#include "services/memoryUsage.hpp"
|
||||||
#include "utilities/debug.hpp"
|
#include "utilities/debug.hpp"
|
||||||
#include "utilities/events.hpp"
|
#include "utilities/events.hpp"
|
||||||
#include "utilities/formatBuffer.hpp"
|
#include "utilities/formatBuffer.hpp"
|
||||||
|
@ -423,6 +424,7 @@ class CollectedHeap : public CHeapObj<mtInternal> {
|
||||||
// Return the SoftRefPolicy for the heap;
|
// Return the SoftRefPolicy for the heap;
|
||||||
virtual SoftRefPolicy* soft_ref_policy() = 0;
|
virtual SoftRefPolicy* soft_ref_policy() = 0;
|
||||||
|
|
||||||
|
virtual MemoryUsage memory_usage();
|
||||||
virtual GrowableArray<GCMemoryManager*> memory_managers() = 0;
|
virtual GrowableArray<GCMemoryManager*> memory_managers() = 0;
|
||||||
virtual GrowableArray<MemoryPool*> memory_pools() = 0;
|
virtual GrowableArray<MemoryPool*> memory_pools() = 0;
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,7 @@ Monitor* DirtyCardQ_CBL_mon = NULL;
|
||||||
Mutex* Shared_DirtyCardQ_lock = NULL;
|
Mutex* Shared_DirtyCardQ_lock = NULL;
|
||||||
Mutex* MarkStackFreeList_lock = NULL;
|
Mutex* MarkStackFreeList_lock = NULL;
|
||||||
Mutex* MarkStackChunkList_lock = NULL;
|
Mutex* MarkStackChunkList_lock = NULL;
|
||||||
|
Mutex* MonitoringSupport_lock = NULL;
|
||||||
Mutex* ParGCRareEvent_lock = NULL;
|
Mutex* ParGCRareEvent_lock = NULL;
|
||||||
Mutex* DerivedPointerTableGC_lock = NULL;
|
Mutex* DerivedPointerTableGC_lock = NULL;
|
||||||
Monitor* CGCPhaseManager_lock = NULL;
|
Monitor* CGCPhaseManager_lock = NULL;
|
||||||
|
@ -216,6 +217,8 @@ void mutex_init() {
|
||||||
|
|
||||||
def(MarkStackFreeList_lock , PaddedMutex , leaf , true, Monitor::_safepoint_check_never);
|
def(MarkStackFreeList_lock , PaddedMutex , leaf , true, Monitor::_safepoint_check_never);
|
||||||
def(MarkStackChunkList_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(ParGCRareEvent_lock , PaddedMutex , leaf , true, Monitor::_safepoint_check_sometimes);
|
||||||
def(DerivedPointerTableGC_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_never);
|
def(DerivedPointerTableGC_lock , PaddedMutex , leaf, true, Monitor::_safepoint_check_never);
|
||||||
|
|
|
@ -94,6 +94,7 @@ extern Mutex* Shared_DirtyCardQ_lock; // Lock protecting dirty card
|
||||||
// non-Java threads.
|
// non-Java threads.
|
||||||
extern Mutex* MarkStackFreeList_lock; // Protects access to the global mark stack free list.
|
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* 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* 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 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
|
extern Monitor* MethodCompileQueue_lock; // a lock held when method compilations are enqueued, dequeued
|
||||||
|
|
|
@ -713,7 +713,12 @@ JVM_END
|
||||||
JVM_ENTRY(jobject, jmm_GetMemoryUsage(JNIEnv* env, jboolean heap))
|
JVM_ENTRY(jobject, jmm_GetMemoryUsage(JNIEnv* env, jboolean heap))
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
|
|
||||||
// Calculate the memory usage
|
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_init = 0;
|
||||||
size_t total_used = 0;
|
size_t total_used = 0;
|
||||||
size_t total_committed = 0;
|
size_t total_committed = 0;
|
||||||
|
@ -723,19 +728,19 @@ JVM_ENTRY(jobject, jmm_GetMemoryUsage(JNIEnv* env, jboolean heap))
|
||||||
|
|
||||||
for (int i = 0; i < MemoryService::num_memory_pools(); i++) {
|
for (int i = 0; i < MemoryService::num_memory_pools(); i++) {
|
||||||
MemoryPool* pool = MemoryService::get_memory_pool(i);
|
MemoryPool* pool = MemoryService::get_memory_pool(i);
|
||||||
if ((heap && pool->is_heap()) || (!heap && pool->is_non_heap())) {
|
if (pool->is_non_heap()) {
|
||||||
MemoryUsage u = pool->get_memory_usage();
|
MemoryUsage u = pool->get_memory_usage();
|
||||||
total_used += u.used();
|
total_used += u.used();
|
||||||
total_committed += u.committed();
|
total_committed += u.committed();
|
||||||
|
|
||||||
if (u.init_size() == (size_t)-1) {
|
if (u.init_size() == MemoryUsage::undefined_size()) {
|
||||||
has_undefined_init_size = true;
|
has_undefined_init_size = true;
|
||||||
}
|
}
|
||||||
if (!has_undefined_init_size) {
|
if (!has_undefined_init_size) {
|
||||||
total_init += u.init_size();
|
total_init += u.init_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (u.max_size() == (size_t)-1) {
|
if (u.max_size() == MemoryUsage::undefined_size()) {
|
||||||
has_undefined_max_size = true;
|
has_undefined_max_size = true;
|
||||||
}
|
}
|
||||||
if (!has_undefined_max_size) {
|
if (!has_undefined_max_size) {
|
||||||
|
@ -745,18 +750,16 @@ JVM_ENTRY(jobject, jmm_GetMemoryUsage(JNIEnv* env, jboolean heap))
|
||||||
}
|
}
|
||||||
|
|
||||||
// if any one of the memory pool has undefined init_size or max_size,
|
// if any one of the memory pool has undefined init_size or max_size,
|
||||||
// set it to -1
|
// set it to MemoryUsage::undefined_size()
|
||||||
if (has_undefined_init_size) {
|
if (has_undefined_init_size) {
|
||||||
total_init = (size_t)-1;
|
total_init = MemoryUsage::undefined_size();
|
||||||
}
|
}
|
||||||
if (has_undefined_max_size) {
|
if (has_undefined_max_size) {
|
||||||
total_max = (size_t)-1;
|
total_max = MemoryUsage::undefined_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryUsage usage((heap ? InitialHeapSize : total_init),
|
usage = MemoryUsage(total_init, total_used, total_committed, total_max);
|
||||||
total_used,
|
}
|
||||||
total_committed,
|
|
||||||
(heap ? Universe::heap()->max_capacity() : total_max));
|
|
||||||
|
|
||||||
Handle obj = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
|
Handle obj = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
|
||||||
return JNIHandles::make_local(env, obj());
|
return JNIHandles::make_local(env, obj());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue