# HG changeset patch # User rkennke # Date 1511541791 -3600 # Fri Nov 24 17:43:11 2017 +0100 # Node ID 903f4826c03317ad01ceb5cffb44d7af37bba821 # Parent f140bebf0348d4493982e31cbedd56feb344d899 [mq]: open.patch diff --git a/src/hotspot/share/gc/cms/cmsHeap.cpp b/src/hotspot/share/gc/cms/cmsHeap.cpp --- a/src/hotspot/share/gc/cms/cmsHeap.cpp +++ b/src/hotspot/share/gc/cms/cmsHeap.cpp @@ -23,17 +23,51 @@ */ #include "precompiled.hpp" +#include "gc/cms/compactibleFreeListSpace.hpp" +#include "gc/cms/concurrentMarkSweepGeneration.hpp" #include "gc/cms/concurrentMarkSweepThread.hpp" #include "gc/cms/cmsHeap.hpp" +#include "gc/cms/parNewGeneration.hpp" #include "gc/cms/vmCMSOperations.hpp" +#include "gc/shared/genMemoryPools.hpp" #include "gc/shared/genOopClosures.inline.hpp" #include "gc/shared/strongRootsScope.hpp" #include "gc/shared/workgroup.hpp" #include "oops/oop.inline.hpp" #include "runtime/vmThread.hpp" +#include "services/memoryManager.hpp" #include "utilities/stack.inline.hpp" -CMSHeap::CMSHeap(GenCollectorPolicy *policy) : GenCollectedHeap(policy) { +class CompactibleFreeListSpacePool : public CollectedMemoryPool { +private: + CompactibleFreeListSpace* _space; +public: + CompactibleFreeListSpacePool(CompactibleFreeListSpace* space, + const char* name, + size_t max_size, + bool support_usage_threshold) : + CollectedMemoryPool(name, space->capacity(), max_size, support_usage_threshold), + _space(space) { + } + + MemoryUsage get_memory_usage() { + size_t max_heap_size = (available_for_allocation() ? max_size() : 0); + size_t used = used_in_bytes(); + size_t committed = _space->capacity(); + + return MemoryUsage(initial_size(), used, committed, max_heap_size); + } + + size_t used_in_bytes() { + return _space->used(); + } +}; + +CMSHeap::CMSHeap(GenCollectorPolicy *policy) : + GenCollectedHeap(policy), _eden_pool(NULL), _survivor_pool(NULL), _old_pool(NULL) { + _young_manager = new GCMemoryManager("ParNew", "end of minor GC"); + _old_manager = new GCMemoryManager("ConcurrentMarkSweep", "end of major GC"); + _workers = new WorkGang("GC Thread", ParallelGCThreads, /* are_GC_task_threads */true, /* are_ConcurrentGC_threads */false); @@ -51,6 +85,32 @@ return JNI_ENOMEM; } + ParNewGeneration* young = (ParNewGeneration*) young_gen(); + _eden_pool = new ContiguousSpacePool(young->eden(), + "Par Eden Space", + young->max_eden_size(), + false); + + _survivor_pool = new SurvivorContiguousSpacePool(young, + "Par Survivor Space", + young->max_survivor_size(), + false); + + ConcurrentMarkSweepGeneration* old = (ConcurrentMarkSweepGeneration*) old_gen(); + _old_pool = new CompactibleFreeListSpacePool(old->cmsSpace(), + "CMS Old Gen", + old->reserved().byte_size(), + true); + + _young_manager->add_pool(_eden_pool); + _young_manager->add_pool(_survivor_pool); + young->set_gc_manager(_young_manager); + + _old_manager->add_pool(_eden_pool); + _old_manager->add_pool(_survivor_pool); + _old_manager->add_pool(_old_pool); + old ->set_gc_manager(_old_manager); + return JNI_OK; } @@ -183,3 +243,18 @@ GenCollectedHeap::gc_epilogue(full); always_do_update_barrier = true; }; + +GrowableArray CMSHeap::memory_managers() { + GrowableArray memory_managers(2); + memory_managers.append(_young_manager); + memory_managers.append(_old_manager); + return memory_managers; +} + +GrowableArray CMSHeap::memory_pools() { + GrowableArray memory_pools(3); + memory_pools.append(_eden_pool); + memory_pools.append(_survivor_pool); + memory_pools.append(_old_pool); + return memory_pools; +} diff --git a/src/hotspot/share/gc/cms/cmsHeap.hpp b/src/hotspot/share/gc/cms/cmsHeap.hpp --- a/src/hotspot/share/gc/cms/cmsHeap.hpp +++ b/src/hotspot/share/gc/cms/cmsHeap.hpp @@ -29,9 +29,12 @@ #include "gc/shared/collectedHeap.hpp" #include "gc/shared/gcCause.hpp" #include "gc/shared/genCollectedHeap.hpp" +#include "utilities/growableArray.hpp" class CLDClosure; class GenCollectorPolicy; +class GCMemoryManager; +class MemoryPool; class OopsInGenClosure; class outputStream; class StrongRootsScope; @@ -80,6 +83,9 @@ void safepoint_synchronize_begin(); void safepoint_synchronize_end(); + virtual GrowableArray memory_managers(); + virtual GrowableArray memory_pools(); + // If "young_gen_as_roots" is false, younger generations are // not scanned as roots; in this case, the caller must be arranging to // scan the younger generations itself. (For example, a generation might @@ -92,8 +98,13 @@ OopsInGenClosure* root_closure, CLDClosure* cld_closure); + GCMemoryManager* old_manager() const { return _old_manager; } + private: WorkGang* _workers; + MemoryPool* _eden_pool; + MemoryPool* _survivor_pool; + MemoryPool* _old_pool; virtual void gc_prologue(bool full); virtual void gc_epilogue(bool full); diff --git a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp --- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp @@ -8116,42 +8116,42 @@ } TraceCMSMemoryManagerStats::TraceCMSMemoryManagerStats(CMSCollector::CollectorState phase, GCCause::Cause cause): TraceMemoryManagerStats() { - + GCMemoryManager* manager = CMSHeap::heap()->old_manager(); switch (phase) { case CMSCollector::InitialMarking: - initialize(true /* fullGC */ , - cause /* cause of the GC */, - true /* recordGCBeginTime */, - true /* recordPreGCUsage */, - false /* recordPeakUsage */, - false /* recordPostGCusage */, - true /* recordAccumulatedGCTime */, - false /* recordGCEndTime */, - false /* countCollection */ ); + initialize(manager /* GC manager */ , + cause /* cause of the GC */, + true /* recordGCBeginTime */, + true /* recordPreGCUsage */, + false /* recordPeakUsage */, + false /* recordPostGCusage */, + true /* recordAccumulatedGCTime */, + false /* recordGCEndTime */, + false /* countCollection */ ); break; case CMSCollector::FinalMarking: - initialize(true /* fullGC */ , - cause /* cause of the GC */, - false /* recordGCBeginTime */, - false /* recordPreGCUsage */, - false /* recordPeakUsage */, - false /* recordPostGCusage */, - true /* recordAccumulatedGCTime */, - false /* recordGCEndTime */, - false /* countCollection */ ); + initialize(manager /* GC manager */ , + cause /* cause of the GC */, + false /* recordGCBeginTime */, + false /* recordPreGCUsage */, + false /* recordPeakUsage */, + false /* recordPostGCusage */, + true /* recordAccumulatedGCTime */, + false /* recordGCEndTime */, + false /* countCollection */ ); break; case CMSCollector::Sweeping: - initialize(true /* fullGC */ , - cause /* cause of the GC */, - false /* recordGCBeginTime */, - false /* recordPreGCUsage */, - true /* recordPeakUsage */, - true /* recordPostGCusage */, - false /* recordAccumulatedGCTime */, - true /* recordGCEndTime */, - true /* countCollection */ ); + initialize(manager /* GC manager */ , + cause /* cause of the GC */, + false /* recordGCBeginTime */, + false /* recordPreGCUsage */, + true /* recordPeakUsage */, + true /* recordPostGCusage */, + false /* recordAccumulatedGCTime */, + true /* recordGCEndTime */, + true /* countCollection */ ); break; default: diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -44,6 +44,7 @@ #include "gc/g1/g1HeapTransition.hpp" #include "gc/g1/g1HeapVerifier.hpp" #include "gc/g1/g1HotCardCache.hpp" +#include "gc/g1/g1MemoryPool.hpp" #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/g1ParScanThreadState.inline.hpp" #include "gc/g1/g1Policy.hpp" @@ -1229,7 +1230,7 @@ const bool do_clear_all_soft_refs = clear_all_soft_refs || collector_policy()->should_clear_all_soft_refs(); - G1FullCollector collector(this, explicit_gc, do_clear_all_soft_refs); + G1FullCollector collector(this, &_full_gc_memory_manager, explicit_gc, do_clear_all_soft_refs); GCTraceTime(Info, gc) tm("Pause Full", NULL, gc_cause(), true); collector.prepare_collection(); @@ -1526,6 +1527,11 @@ CollectedHeap(), _young_gen_sampling_thread(NULL), _collector_policy(collector_policy), + _memory_manager("G1 Young Generation", "end of minor GC"), + _full_gc_memory_manager("G1 Old Generation", "end of major GC"), + _eden_pool(NULL), + _survivor_pool(NULL), + _old_pool(NULL), _gc_timer_stw(new (ResourceObj::C_HEAP, mtGC) STWGCTimer()), _gc_tracer_stw(new (ResourceObj::C_HEAP, mtGC) G1NewTracer()), _g1_policy(create_g1_policy(_gc_timer_stw)), @@ -1821,6 +1827,17 @@ // values in the heap have been properly initialized. _g1mm = new G1MonitoringSupport(this); + _eden_pool = new G1EdenPool(this); + _survivor_pool = new G1SurvivorPool(this); + _old_pool = new G1OldGenPool(this); + + _full_gc_memory_manager.add_pool(_eden_pool); + _full_gc_memory_manager.add_pool(_survivor_pool); + _full_gc_memory_manager.add_pool(_old_pool); + + _memory_manager.add_pool(_eden_pool); + _memory_manager.add_pool(_survivor_pool); + G1StringDedup::initialize(); _preserved_marks_set.init(ParallelGCThreads); @@ -2954,7 +2971,7 @@ log_info(gc,task)("Using %u workers of %u for evacuation", active_workers, workers()->total_workers()); TraceCollectorStats tcs(g1mm()->incremental_collection_counters()); - TraceMemoryManagerStats tms(false /* fullGC */, gc_cause()); + TraceMemoryManagerStats tms(&_memory_manager, gc_cause()); // If the secondary_free_list is not empty, append it to the // free_list. No need to wait for the cleanup operation to finish; @@ -5368,3 +5385,18 @@ RebuildStrongCodeRootClosure blob_cl(this); CodeCache::blobs_do(&blob_cl); } + +GrowableArray G1CollectedHeap::memory_managers() { + GrowableArray memory_managers(2); + memory_managers.append(&_memory_manager); + memory_managers.append(&_full_gc_memory_manager); + return memory_managers; +} + +GrowableArray G1CollectedHeap::memory_pools() { + GrowableArray memory_pools(3); + memory_pools.append(_eden_pool); + memory_pools.append(_survivor_pool); + memory_pools.append(_old_pool); + return memory_pools; +} diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -50,6 +50,7 @@ #include "gc/shared/plab.hpp" #include "gc/shared/preservedMarks.hpp" #include "memory/memRegion.hpp" +#include "services/memoryManager.hpp" #include "utilities/stack.hpp" // A "G1CollectedHeap" is an implementation of a java heap for HotSpot. @@ -64,6 +65,7 @@ class G1ParScanThreadState; class G1ParScanThreadStateSet; class G1ParScanThreadState; +class MemoryPool; class ObjectClosure; class SpaceClosure; class CompactibleSpaceClosure; @@ -149,6 +151,13 @@ WorkGang* _workers; G1CollectorPolicy* _collector_policy; + GCMemoryManager _memory_manager; + GCMemoryManager _full_gc_memory_manager; + + MemoryPool* _eden_pool; + MemoryPool* _survivor_pool; + MemoryPool* _old_pool; + static size_t _humongous_object_threshold_in_words; // The secondary free list which contains regions that have been @@ -1006,6 +1015,9 @@ // Adaptive size policy. No such thing for g1. virtual AdaptiveSizePolicy* size_policy() { return NULL; } + virtual GrowableArray memory_managers(); + virtual GrowableArray memory_pools(); + // The rem set and barrier set. G1RemSet* g1_rem_set() const { return _g1_rem_set; } diff --git a/src/hotspot/share/gc/g1/g1FullCollector.cpp b/src/hotspot/share/gc/g1/g1FullCollector.cpp --- a/src/hotspot/share/gc/g1/g1FullCollector.cpp +++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp @@ -71,9 +71,9 @@ return _heap->ref_processor_stw(); } -G1FullCollector::G1FullCollector(G1CollectedHeap* heap, bool explicit_gc, bool clear_soft_refs) : +G1FullCollector::G1FullCollector(G1CollectedHeap* heap, GCMemoryManager* memory_manager, bool explicit_gc, bool clear_soft_refs) : _heap(heap), - _scope(explicit_gc, clear_soft_refs), + _scope(memory_manager, explicit_gc, clear_soft_refs), _num_workers(heap->workers()->active_workers()), _oop_queue_set(_num_workers), _array_queue_set(_num_workers), diff --git a/src/hotspot/share/gc/g1/g1FullCollector.hpp b/src/hotspot/share/gc/g1/g1FullCollector.hpp --- a/src/hotspot/share/gc/g1/g1FullCollector.hpp +++ b/src/hotspot/share/gc/g1/g1FullCollector.hpp @@ -39,6 +39,7 @@ class G1FullGCMarker; class G1FullGCScope; class G1FullGCCompactionPoint; +class GCMemoryManager; class ReferenceProcessor; // The G1FullCollector holds data associated with the current Full GC. @@ -56,7 +57,7 @@ ReferenceProcessorIsAliveMutator _is_alive_mutator; public: - G1FullCollector(G1CollectedHeap* heap, bool explicit_gc, bool clear_soft_refs); + G1FullCollector(G1CollectedHeap* heap, GCMemoryManager* memory_manager, bool explicit_gc, bool clear_soft_refs); ~G1FullCollector(); void prepare_collection(); diff --git a/src/hotspot/share/gc/g1/g1FullGCScope.cpp b/src/hotspot/share/gc/g1/g1FullGCScope.cpp --- a/src/hotspot/share/gc/g1/g1FullGCScope.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCScope.cpp @@ -25,7 +25,7 @@ #include "precompiled.hpp" #include "gc/g1/g1FullGCScope.hpp" -G1FullGCScope::G1FullGCScope(bool explicit_gc, bool clear_soft) : +G1FullGCScope::G1FullGCScope(GCMemoryManager* memory_manager, bool explicit_gc, bool clear_soft) : _rm(), _explicit_gc(explicit_gc), _g1h(G1CollectedHeap::heap()), @@ -36,7 +36,7 @@ _active(), _cpu_time(), _soft_refs(clear_soft, _g1h->collector_policy()), - _memory_stats(true, _g1h->gc_cause()), + _memory_stats(memory_manager, _g1h->gc_cause()), _collector_stats(_g1h->g1mm()->full_collection_counters()), _heap_transition(_g1h) { _timer.register_gc_start(); diff --git a/src/hotspot/share/gc/g1/g1FullGCScope.hpp b/src/hotspot/share/gc/g1/g1FullGCScope.hpp --- a/src/hotspot/share/gc/g1/g1FullGCScope.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCScope.hpp @@ -37,6 +37,8 @@ #include "memory/allocation.hpp" #include "services/memoryService.hpp" +class GCMemoryManager; + // Class used to group scoped objects used in the Full GC together. class G1FullGCScope : public StackObj { ResourceMark _rm; @@ -54,7 +56,7 @@ G1HeapTransition _heap_transition; public: - G1FullGCScope(bool explicit_gc, bool clear_soft); + G1FullGCScope(GCMemoryManager* memory_manager, bool explicit_gc, bool clear_soft); ~G1FullGCScope(); bool is_explicit_gc(); diff --git a/src/hotspot/share/gc/g1/g1MemoryPool.cpp b/src/hotspot/share/gc/g1/g1MemoryPool.cpp new file mode 100644 --- /dev/null +++ b/src/hotspot/share/gc/g1/g1MemoryPool.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2007, 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. + * + */ + +#include "precompiled.hpp" +#include "gc/g1/g1CollectedHeap.hpp" +#include "gc/g1/g1MemoryPool.hpp" +#include "gc/g1/heapRegion.hpp" + +G1MemoryPoolSuper::G1MemoryPoolSuper(G1CollectedHeap* g1h, + const char* name, + size_t init_size, + size_t max_size, + bool support_usage_threshold) : + _g1mm(g1h->g1mm()), CollectedMemoryPool(name, + init_size, + max_size, + support_usage_threshold) { + assert(UseG1GC, "sanity"); +} + +G1EdenPool::G1EdenPool(G1CollectedHeap* g1h) : + G1MemoryPoolSuper(g1h, + "G1 Eden Space", + g1h->g1mm()->eden_space_committed(), /* init_size */ + _undefined_max, + false /* support_usage_threshold */) { } + +MemoryUsage G1EdenPool::get_memory_usage() { + size_t initial_sz = initial_size(); + size_t max_sz = max_size(); + size_t used = used_in_bytes(); + size_t committed = _g1mm->eden_space_committed(); + + return MemoryUsage(initial_sz, used, committed, max_sz); +} + +G1SurvivorPool::G1SurvivorPool(G1CollectedHeap* g1h) : + G1MemoryPoolSuper(g1h, + "G1 Survivor Space", + g1h->g1mm()->survivor_space_committed(), /* init_size */ + _undefined_max, + false /* support_usage_threshold */) { } + +MemoryUsage G1SurvivorPool::get_memory_usage() { + size_t initial_sz = initial_size(); + size_t max_sz = max_size(); + size_t used = used_in_bytes(); + size_t committed = _g1mm->survivor_space_committed(); + + return MemoryUsage(initial_sz, used, committed, max_sz); +} + +G1OldGenPool::G1OldGenPool(G1CollectedHeap* g1h) : + G1MemoryPoolSuper(g1h, + "G1 Old Gen", + g1h->g1mm()->old_space_committed(), /* init_size */ + g1h->g1mm()->old_gen_max(), + true /* support_usage_threshold */) { } + +MemoryUsage G1OldGenPool::get_memory_usage() { + size_t initial_sz = initial_size(); + size_t max_sz = max_size(); + size_t used = used_in_bytes(); + size_t committed = _g1mm->old_space_committed(); + + return MemoryUsage(initial_sz, used, committed, max_sz); +} diff --git a/src/hotspot/share/gc/g1/g1MemoryPool.hpp b/src/hotspot/share/gc/g1/g1MemoryPool.hpp new file mode 100644 --- /dev/null +++ b/src/hotspot/share/gc/g1/g1MemoryPool.hpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2007, 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_GC_G1_G1MEMORYPOOL_HPP +#define SHARE_VM_GC_G1_G1MEMORYPOOL_HPP + +#include "gc/g1/g1MonitoringSupport.hpp" +#include "services/memoryPool.hpp" +#include "services/memoryUsage.hpp" + +// This file contains the three classes that represent the memory +// pools of the G1 spaces: G1EdenPool, G1SurvivorPool, and +// G1OldGenPool. In G1, unlike our other GCs, we do not have a +// physical space for each of those spaces. Instead, we allocate +// regions for all three spaces out of a single pool of regions (that +// pool basically covers the entire heap). As a result, the eden, +// survivor, and old gen are considered logical spaces in G1, as each +// is a set of non-contiguous regions. This is also reflected in the +// way we map them to memory pools here. The easiest way to have done +// this would have been to map the entire G1 heap to a single memory +// pool. However, it's helpful to show how large the eden and survivor +// get, as this does affect the performance and behavior of G1. Which +// is why we introduce the three memory pools implemented here. +// +// See comments in g1MonitoringSupport.hpp for additional details +// on this model. +// + +class G1CollectedHeap; + +// This class is shared by the three G1 memory pool classes +// (G1EdenPool, G1SurvivorPool, G1OldGenPool). +class G1MemoryPoolSuper : public CollectedMemoryPool { +protected: + const static size_t _undefined_max = (size_t) -1; + G1MonitoringSupport* _g1mm; + + // Would only be called from subclasses. + G1MemoryPoolSuper(G1CollectedHeap* g1h, + const char* name, + size_t init_size, + size_t max_size, + bool support_usage_threshold); +}; + +// Memory pool that represents the G1 eden. +class G1EdenPool : public G1MemoryPoolSuper { +public: + G1EdenPool(G1CollectedHeap* g1h); + + size_t used_in_bytes() { + return _g1mm->eden_space_used(); + } + size_t max_size() const { + return _undefined_max; + } + MemoryUsage get_memory_usage(); +}; + +// Memory pool that represents the G1 survivor. +class G1SurvivorPool : public G1MemoryPoolSuper { +public: + G1SurvivorPool(G1CollectedHeap* g1h); + + size_t used_in_bytes() { + return _g1mm->survivor_space_used(); + } + size_t max_size() const { + return _undefined_max; + } + MemoryUsage get_memory_usage(); +}; + +// Memory pool that represents the G1 old gen. +class G1OldGenPool : public G1MemoryPoolSuper { +public: + G1OldGenPool(G1CollectedHeap* g1h); + + size_t used_in_bytes() { + return _g1mm->old_space_used(); + } + size_t max_size() const { + return _g1mm->old_gen_max(); + } + MemoryUsage get_memory_usage(); +}; + +#endif // SHARE_VM_GC_G1_G1MEMORYPOOL_HPP diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp @@ -33,6 +33,7 @@ #include "gc/parallel/parallelScavengeHeap.inline.hpp" #include "gc/parallel/psAdaptiveSizePolicy.hpp" #include "gc/parallel/psMarkSweep.hpp" +#include "gc/parallel/psMemoryPool.hpp" #include "gc/parallel/psParallelCompact.inline.hpp" #include "gc/parallel/psPromotionManager.hpp" #include "gc/parallel/psScavenge.hpp" @@ -45,6 +46,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/java.hpp" #include "runtime/vmThread.hpp" +#include "services/memoryManager.hpp" #include "services/memTracker.hpp" #include "utilities/vmError.hpp" @@ -116,6 +118,30 @@ return JNI_ENOMEM; } + + _eden_pool = new EdenMutableSpacePool(_young_gen, + _young_gen->eden_space(), + "PS Eden Space", + false /* support_usage_threshold */); + + _survivor_pool = new SurvivorMutableSpacePool(_young_gen, + "PS Survivor Space", + false /* support_usage_threshold */); + + _old_pool = new PSGenerationPool(_old_gen, + "PS Old Gen", + true /* support_usage_threshold */); + + _young_manager = new GCMemoryManager("PS Scavenge", "end of minor GC"); + _old_manager = new GCMemoryManager("PS MarkSweep", "end of major GC"); + + _old_manager->add_pool(_eden_pool); + _old_manager->add_pool(_survivor_pool); + _old_manager->add_pool(_old_pool); + + _young_manager->add_pool(_eden_pool); + _young_manager->add_pool(_survivor_pool); + return JNI_OK; } @@ -674,3 +700,19 @@ void ParallelScavengeHeap::verify_nmethod(nmethod* nm) { CodeCache::verify_scavenge_root_nmethod(nm); } + +GrowableArray ParallelScavengeHeap::memory_managers() { + GrowableArray memory_managers(2); + memory_managers.append(_young_manager); + memory_managers.append(_old_manager); + return memory_managers; +} + +GrowableArray ParallelScavengeHeap::memory_pools() { + GrowableArray memory_pools(3); + memory_pools.append(_eden_pool); + memory_pools.append(_survivor_pool); + memory_pools.append(_old_pool); + return memory_pools; +} + diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -36,11 +36,14 @@ #include "gc/shared/gcWhen.hpp" #include "gc/shared/strongRootsScope.hpp" #include "memory/metaspace.hpp" +#include "utilities/growableArray.hpp" #include "utilities/ostream.hpp" class AdjoiningGenerations; class GCHeapSummary; class GCTaskManager; +class MemoryManager; +class MemoryPool; class PSAdaptiveSizePolicy; class PSHeapSummary; @@ -64,6 +67,13 @@ // The task manager static GCTaskManager* _gc_task_manager; + GCMemoryManager* _young_manager; + GCMemoryManager* _old_manager; + + MemoryPool* _eden_pool; + MemoryPool* _survivor_pool; + MemoryPool* _old_pool; + void trace_heap(GCWhen::Type when, const GCTracer* tracer); protected: @@ -94,6 +104,9 @@ virtual CollectorPolicy* collector_policy() const { return _collector_policy; } + virtual GrowableArray memory_managers(); + virtual GrowableArray memory_pools(); + static PSYoungGen* young_gen() { return _young_gen; } static PSOldGen* old_gen() { return _old_gen; } @@ -244,6 +257,9 @@ ParStrongRootsScope(); ~ParStrongRootsScope(); }; + + GCMemoryManager* old_gc_manager() const { return _old_manager; } + GCMemoryManager* young_gc_manager() const { return _young_manager; } }; // Simple class for storing info about the heap at the start of GC, to be used diff --git a/src/hotspot/share/gc/parallel/psMarkSweep.cpp b/src/hotspot/share/gc/parallel/psMarkSweep.cpp --- a/src/hotspot/share/gc/parallel/psMarkSweep.cpp +++ b/src/hotspot/share/gc/parallel/psMarkSweep.cpp @@ -172,7 +172,7 @@ heap->pre_full_gc_dump(_gc_timer); TraceCollectorStats tcs(counters()); - TraceMemoryManagerStats tms(true /* Full GC */,gc_cause); + TraceMemoryManagerStats tms(heap->old_gc_manager(),gc_cause); if (log_is_enabled(Debug, gc, heap, exit)) { accumulated_time()->start(); diff --git a/src/hotspot/share/gc/parallel/psMemoryPool.cpp b/src/hotspot/share/gc/parallel/psMemoryPool.cpp new file mode 100644 --- /dev/null +++ b/src/hotspot/share/gc/parallel/psMemoryPool.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2007, 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. + * + */ + +#include "precompiled.hpp" +#include "gc/parallel/psMemoryPool.hpp" + +PSGenerationPool::PSGenerationPool(PSOldGen* old_gen, + const char* name, + bool support_usage_threshold) : + CollectedMemoryPool(name, old_gen->capacity_in_bytes(), + old_gen->reserved().byte_size(), support_usage_threshold), _old_gen(old_gen) { +} + +MemoryUsage PSGenerationPool::get_memory_usage() { + size_t maxSize = (available_for_allocation() ? max_size() : 0); + size_t used = used_in_bytes(); + size_t committed = _old_gen->capacity_in_bytes(); + + return MemoryUsage(initial_size(), used, committed, maxSize); +} + +// The max size of EdenMutableSpacePool = +// max size of the PSYoungGen - capacity of two survivor spaces +// +// Max size of PS eden space is changing due to ergonomic. +// PSYoungGen, PSOldGen, Eden, Survivor spaces are all resizable. +// +EdenMutableSpacePool::EdenMutableSpacePool(PSYoungGen* young_gen, + MutableSpace* space, + const char* name, + bool support_usage_threshold) : + CollectedMemoryPool(name, space->capacity_in_bytes(), + (young_gen->max_size() - young_gen->from_space()->capacity_in_bytes() - young_gen->to_space()->capacity_in_bytes()), + support_usage_threshold), + _young_gen(young_gen), + _space(space) { +} + +MemoryUsage EdenMutableSpacePool::get_memory_usage() { + size_t maxSize = (available_for_allocation() ? max_size() : 0); + size_t used = used_in_bytes(); + size_t committed = _space->capacity_in_bytes(); + + return MemoryUsage(initial_size(), used, committed, maxSize); +} + +// The max size of SurvivorMutableSpacePool = +// current capacity of the from-space +// +// PS from and to survivor spaces could have different sizes. +// +SurvivorMutableSpacePool::SurvivorMutableSpacePool(PSYoungGen* young_gen, + const char* name, + bool support_usage_threshold) : + CollectedMemoryPool(name, young_gen->from_space()->capacity_in_bytes(), + young_gen->from_space()->capacity_in_bytes(), + support_usage_threshold), _young_gen(young_gen) { +} + +MemoryUsage SurvivorMutableSpacePool::get_memory_usage() { + size_t maxSize = (available_for_allocation() ? max_size() : 0); + size_t used = used_in_bytes(); + size_t committed = committed_in_bytes(); + return MemoryUsage(initial_size(), used, committed, maxSize); +} diff --git a/src/hotspot/share/gc/parallel/psMemoryPool.hpp b/src/hotspot/share/gc/parallel/psMemoryPool.hpp new file mode 100644 --- /dev/null +++ b/src/hotspot/share/gc/parallel/psMemoryPool.hpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2007, 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_SERVICES_PSMEMORYPOOL_HPP +#define SHARE_VM_SERVICES_PSMEMORYPOOL_HPP + +#include "gc/parallel/mutableSpace.hpp" +#include "gc/parallel/psOldGen.hpp" +#include "gc/parallel/psYoungGen.hpp" +#include "services/memoryPool.hpp" +#include "services/memoryUsage.hpp" + +class PSGenerationPool : public CollectedMemoryPool { +private: + PSOldGen* _old_gen; + +public: + PSGenerationPool(PSOldGen* pool, const char* name, bool support_usage_threshold); + + MemoryUsage get_memory_usage(); + size_t used_in_bytes() { return _old_gen->used_in_bytes(); } + size_t max_size() const { return _old_gen->reserved().byte_size(); } +}; + +class EdenMutableSpacePool : public CollectedMemoryPool { +private: + PSYoungGen* _young_gen; + MutableSpace* _space; + +public: + EdenMutableSpacePool(PSYoungGen* young_gen, + MutableSpace* space, + const char* name, + bool support_usage_threshold); + + MutableSpace* space() { return _space; } + MemoryUsage get_memory_usage(); + size_t used_in_bytes() { return space()->used_in_bytes(); } + size_t max_size() const { + // Eden's max_size = max_size of Young Gen - the current committed size of survivor spaces + return _young_gen->max_size() - _young_gen->from_space()->capacity_in_bytes() - _young_gen->to_space()->capacity_in_bytes(); + } +}; + +class SurvivorMutableSpacePool : public CollectedMemoryPool { +private: + PSYoungGen* _young_gen; + +public: + SurvivorMutableSpacePool(PSYoungGen* young_gen, + const char* name, + bool support_usage_threshold); + + MemoryUsage get_memory_usage(); + + size_t used_in_bytes() { + return _young_gen->from_space()->used_in_bytes(); + } + size_t committed_in_bytes() { + return _young_gen->from_space()->capacity_in_bytes(); + } + size_t max_size() const { + // Return current committed size of the from-space + return _young_gen->from_space()->capacity_in_bytes(); + } +}; + +#endif // SHARE_VM_SERVICES_PSMEMORYPOOL_HPP diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -1772,7 +1772,7 @@ heap->pre_full_gc_dump(&_gc_timer); TraceCollectorStats tcs(counters()); - TraceMemoryManagerStats tms(true /* Full GC */,gc_cause); + TraceMemoryManagerStats tms(heap->old_gc_manager(), gc_cause); if (log_is_enabled(Debug, gc, heap, exit)) { accumulated_time()->start(); diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -305,7 +305,7 @@ GCTraceCPUTime tcpu; GCTraceTime(Info, gc) tm("Pause Young", NULL, gc_cause, true); TraceCollectorStats tcs(counters()); - TraceMemoryManagerStats tms(false /* not full GC */,gc_cause); + TraceMemoryManagerStats tms(heap->young_gc_manager(), gc_cause); if (log_is_enabled(Debug, gc, heap, exit)) { accumulated_time()->start(); diff --git a/src/hotspot/share/gc/serial/serialHeap.cpp b/src/hotspot/share/gc/serial/serialHeap.cpp --- a/src/hotspot/share/gc/serial/serialHeap.cpp +++ b/src/hotspot/share/gc/serial/serialHeap.cpp @@ -23,9 +23,47 @@ */ #include "precompiled.hpp" +#include "gc/serial/defNewGeneration.hpp" #include "gc/serial/serialHeap.hpp" +#include "gc/shared/genMemoryPools.hpp" +#include "services/memoryManager.hpp" -SerialHeap::SerialHeap(GenCollectorPolicy* policy) : GenCollectedHeap(policy) {} +SerialHeap::SerialHeap(GenCollectorPolicy* policy) : + GenCollectedHeap(policy), _eden_pool(NULL), _survivor_pool(NULL), _old_pool(NULL) { + _young_manager = new GCMemoryManager("Copy", "end of minor GC"); + _old_manager = new GCMemoryManager("MarkSweepCompact", "end of major GC"); +} + +jint SerialHeap::initialize() { + jint status = GenCollectedHeap::initialize(); + if (status != JNI_OK) return status; + + DefNewGeneration* young = (DefNewGeneration*) young_gen(); + + // Add a memory pool for each space and young gen doesn't + // support low memory detection as it is expected to get filled up. + _eden_pool = new ContiguousSpacePool(young->eden(), + "Eden Space", + young->max_eden_size(), + false /* support_usage_threshold */); + _survivor_pool = new SurvivorContiguousSpacePool(young, + "Survivor Space", + young->max_survivor_size(), + false /* support_usage_threshold */); + Generation* old = old_gen(); + _old_pool = new GenerationPool(old, "Tenured Gen", true); + + _young_manager->add_pool(_eden_pool); + _young_manager->add_pool(_survivor_pool); + young->set_gc_manager(_young_manager); + + _old_manager->add_pool(_eden_pool); + _old_manager->add_pool(_survivor_pool); + _old_manager->add_pool(_old_pool); + old->set_gc_manager(_old_manager); + + return JNI_OK; +} void SerialHeap::check_gen_kinds() { assert(young_gen()->kind() == Generation::DefNew, @@ -33,3 +71,18 @@ assert(old_gen()->kind() == Generation::MarkSweepCompact, "Wrong generation kind"); } + +GrowableArray SerialHeap::memory_managers() { + GrowableArray memory_managers(2); + memory_managers.append(_young_manager); + memory_managers.append(_old_manager); + return memory_managers; +} + +GrowableArray SerialHeap::memory_pools() { + GrowableArray memory_pools(3); + memory_pools.append(_eden_pool); + memory_pools.append(_survivor_pool); + memory_pools.append(_old_pool); + return memory_pools; +} diff --git a/src/hotspot/share/gc/serial/serialHeap.hpp b/src/hotspot/share/gc/serial/serialHeap.hpp --- a/src/hotspot/share/gc/serial/serialHeap.hpp +++ b/src/hotspot/share/gc/serial/serialHeap.hpp @@ -26,10 +26,17 @@ #define SHARE_VM_GC_SERIAL_SERIALHEAP_HPP #include "gc/shared/genCollectedHeap.hpp" +#include "utilities/growableArray.hpp" class GenCollectorPolicy; +class GCMemoryManager; +class MemoryPool; class SerialHeap : public GenCollectedHeap { + MemoryPool* _eden_pool; + MemoryPool* _survivor_pool; + MemoryPool* _old_pool; + protected: virtual void check_gen_kinds(); @@ -44,6 +51,11 @@ return "Serial"; } + virtual jint initialize(); + + virtual GrowableArray memory_managers(); + virtual GrowableArray memory_pools(); + // override virtual bool is_in_closed_subset(const void* p) const { return is_in(p); @@ -52,7 +64,6 @@ virtual bool card_mark_must_follow_store() const { return false; } - }; #endif // SHARE_VM_GC_CMS_CMSHEAP_HPP diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp --- a/src/hotspot/share/gc/shared/collectedHeap.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp @@ -34,6 +34,7 @@ #include "utilities/debug.hpp" #include "utilities/events.hpp" #include "utilities/formatBuffer.hpp" +#include "utilities/growableArray.hpp" // A "CollectedHeap" is an implementation of a java heap for HotSpot. This // is an abstract class: there may be many different kinds of heaps. This @@ -46,6 +47,8 @@ class GCHeapSummary; class GCTimer; class GCTracer; +class GCMemoryManager; +class MemoryPool; class MetaspaceSummary; class Thread; class ThreadClosure; @@ -485,6 +488,9 @@ // Return the CollectorPolicy for the heap virtual CollectorPolicy* collector_policy() const = 0; + virtual GrowableArray memory_managers() = 0; + virtual GrowableArray memory_pools() = 0; + // Iterate over all objects, calling "cl.do_object" on each. virtual void object_iterate(ObjectClosure* cl) = 0; diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.cpp b/src/hotspot/share/gc/shared/genCollectedHeap.cpp --- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp @@ -270,7 +270,7 @@ FormatBuffer<> title("Collect gen: %s", gen->short_name()); GCTraceTime(Trace, gc, phases) t1(title); TraceCollectorStats tcs(gen->counters()); - TraceMemoryManagerStats tmms(gen->kind(),gc_cause()); + TraceMemoryManagerStats tmms(gen->gc_manager(), gc_cause()); gen->stat_record()->invocations++; gen->stat_record()->accumulated_time.start(); diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.hpp b/src/hotspot/share/gc/shared/genCollectedHeap.hpp --- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp @@ -112,6 +112,9 @@ // (gen-specific) roots processing. SubTasksDone* _process_strong_tasks; + GCMemoryManager* _young_manager; + GCMemoryManager* _old_manager; + // Helper functions for allocation HeapWord* attempt_allocation(size_t size, bool is_tlab, diff --git a/src/hotspot/share/gc/shared/genMemoryPools.cpp b/src/hotspot/share/gc/shared/genMemoryPools.cpp new file mode 100644 --- /dev/null +++ b/src/hotspot/share/gc/shared/genMemoryPools.cpp @@ -0,0 +1,92 @@ +/* + * 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. + * + */ + +#include "precompiled.hpp" +#include "gc/serial/defNewGeneration.hpp" +#include "gc/shared/generation.hpp" +#include "gc/shared/genMemoryPools.hpp" +#include "gc/shared/space.hpp" + +ContiguousSpacePool::ContiguousSpacePool(ContiguousSpace* space, + const char* name, + size_t max_size, + bool support_usage_threshold) : + CollectedMemoryPool(name, space->capacity(), max_size, + support_usage_threshold), _space(space) { +} + +size_t ContiguousSpacePool::used_in_bytes() { + return space()->used(); +} + +MemoryUsage ContiguousSpacePool::get_memory_usage() { + size_t maxSize = (available_for_allocation() ? max_size() : 0); + size_t used = used_in_bytes(); + size_t committed = _space->capacity(); + + return MemoryUsage(initial_size(), used, committed, maxSize); +} + +SurvivorContiguousSpacePool::SurvivorContiguousSpacePool(DefNewGeneration* young_gen, + const char* name, + size_t max_size, + bool support_usage_threshold) : + CollectedMemoryPool(name, young_gen->from()->capacity(), max_size, + support_usage_threshold), _young_gen(young_gen) { +} + +size_t SurvivorContiguousSpacePool::used_in_bytes() { + return _young_gen->from()->used(); +} + +size_t SurvivorContiguousSpacePool::committed_in_bytes() { + return _young_gen->from()->capacity(); +} + +MemoryUsage SurvivorContiguousSpacePool::get_memory_usage() { + size_t maxSize = (available_for_allocation() ? max_size() : 0); + size_t used = used_in_bytes(); + size_t committed = committed_in_bytes(); + + return MemoryUsage(initial_size(), used, committed, maxSize); +} + +GenerationPool::GenerationPool(Generation* gen, + const char* name, + bool support_usage_threshold) : + CollectedMemoryPool(name, gen->capacity(), gen->max_capacity(), + support_usage_threshold), _gen(gen) { +} + +size_t GenerationPool::used_in_bytes() { + return _gen->used(); +} + +MemoryUsage GenerationPool::get_memory_usage() { + size_t used = used_in_bytes(); + size_t committed = _gen->capacity(); + size_t maxSize = (available_for_allocation() ? max_size() : 0); + + return MemoryUsage(initial_size(), used, committed, maxSize); +} diff --git a/src/hotspot/share/gc/shared/genMemoryPools.hpp b/src/hotspot/share/gc/shared/genMemoryPools.hpp new file mode 100644 --- /dev/null +++ b/src/hotspot/share/gc/shared/genMemoryPools.hpp @@ -0,0 +1,75 @@ +/* + * 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. + * + */ + +#ifndef SHARE_VM_GC_SHARED_GENMEMORYPOOLS_HPP +#define SHARE_VM_GC_SHARED_GENMEMORYPOOLS_HPP + +#include "services/memoryPool.hpp" + +class ContiguousSpace; +class DefNewGeneration; +class Generation; + +class ContiguousSpacePool : public CollectedMemoryPool { +private: + ContiguousSpace* _space; + +public: + ContiguousSpacePool(ContiguousSpace* space, + const char* name, + size_t max_size, + bool support_usage_threshold); + + ContiguousSpace* space() { return _space; } + MemoryUsage get_memory_usage(); + size_t used_in_bytes(); +}; + +class SurvivorContiguousSpacePool : public CollectedMemoryPool { +private: + DefNewGeneration* _young_gen; + +public: + SurvivorContiguousSpacePool(DefNewGeneration* young_gen, + const char* name, + size_t max_size, + bool support_usage_threshold); + + MemoryUsage get_memory_usage(); + + size_t used_in_bytes(); + size_t committed_in_bytes(); +}; + +class GenerationPool : public CollectedMemoryPool { +private: + Generation* _gen; +public: + GenerationPool(Generation* gen, const char* name, bool support_usage_threshold); + + MemoryUsage get_memory_usage(); + size_t used_in_bytes(); +}; + +#endif // SHARE_VM_GC_SHARED_GENMEMORYPOOLS_HPP diff --git a/src/hotspot/share/gc/shared/generation.cpp b/src/hotspot/share/gc/shared/generation.cpp --- a/src/hotspot/share/gc/shared/generation.cpp +++ b/src/hotspot/share/gc/shared/generation.cpp @@ -44,7 +44,8 @@ #include "utilities/events.hpp" Generation::Generation(ReservedSpace rs, size_t initial_size) : - _ref_processor(NULL) { + _ref_processor(NULL), + _gc_manager(NULL) { if (!_virtual_space.initialize(rs, initial_size)) { vm_exit_during_initialization("Could not reserve enough space for " "object heap"); diff --git a/src/hotspot/share/gc/shared/generation.hpp b/src/hotspot/share/gc/shared/generation.hpp --- a/src/hotspot/share/gc/shared/generation.hpp +++ b/src/hotspot/share/gc/shared/generation.hpp @@ -86,6 +86,8 @@ MemRegion _prev_used_region; // for collectors that want to "remember" a value for // used region at some specific point during collection. + GCMemoryManager* _gc_manager; + protected: // Minimum and maximum addresses for memory reserved (not necessarily // committed) for generation. @@ -554,6 +556,16 @@ // Performance Counter support virtual void update_counters() = 0; virtual CollectorCounters* counters() { return _gc_counters; } + + GCMemoryManager* gc_manager() const { + assert(_gc_manager != NULL, "not initialized yet"); + return _gc_manager; + } + + void set_gc_manager(GCMemoryManager* gc_manager) { + _gc_manager = gc_manager; + } + }; #endif // SHARE_VM_GC_SHARED_GENERATION_HPP diff --git a/src/hotspot/share/services/g1MemoryPool.cpp b/src/hotspot/share/services/g1MemoryPool.cpp deleted file mode 100644 --- a/src/hotspot/share/services/g1MemoryPool.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2007, 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. - * - */ - -#include "precompiled.hpp" -#include "gc/g1/g1CollectedHeap.hpp" -#include "gc/g1/heapRegion.hpp" -#include "services/g1MemoryPool.hpp" - -G1MemoryPoolSuper::G1MemoryPoolSuper(G1CollectedHeap* g1h, - const char* name, - size_t init_size, - size_t max_size, - bool support_usage_threshold) : - _g1mm(g1h->g1mm()), CollectedMemoryPool(name, - MemoryPool::Heap, - init_size, - max_size, - support_usage_threshold) { - assert(UseG1GC, "sanity"); -} - -G1EdenPool::G1EdenPool(G1CollectedHeap* g1h) : - G1MemoryPoolSuper(g1h, - "G1 Eden Space", - g1h->g1mm()->eden_space_committed(), /* init_size */ - _undefined_max, - false /* support_usage_threshold */) { } - -MemoryUsage G1EdenPool::get_memory_usage() { - size_t initial_sz = initial_size(); - size_t max_sz = max_size(); - size_t used = used_in_bytes(); - size_t committed = _g1mm->eden_space_committed(); - - return MemoryUsage(initial_sz, used, committed, max_sz); -} - -G1SurvivorPool::G1SurvivorPool(G1CollectedHeap* g1h) : - G1MemoryPoolSuper(g1h, - "G1 Survivor Space", - g1h->g1mm()->survivor_space_committed(), /* init_size */ - _undefined_max, - false /* support_usage_threshold */) { } - -MemoryUsage G1SurvivorPool::get_memory_usage() { - size_t initial_sz = initial_size(); - size_t max_sz = max_size(); - size_t used = used_in_bytes(); - size_t committed = _g1mm->survivor_space_committed(); - - return MemoryUsage(initial_sz, used, committed, max_sz); -} - -G1OldGenPool::G1OldGenPool(G1CollectedHeap* g1h) : - G1MemoryPoolSuper(g1h, - "G1 Old Gen", - g1h->g1mm()->old_space_committed(), /* init_size */ - g1h->g1mm()->old_gen_max(), - true /* support_usage_threshold */) { } - -MemoryUsage G1OldGenPool::get_memory_usage() { - size_t initial_sz = initial_size(); - size_t max_sz = max_size(); - size_t used = used_in_bytes(); - size_t committed = _g1mm->old_space_committed(); - - return MemoryUsage(initial_sz, used, committed, max_sz); -} diff --git a/src/hotspot/share/services/g1MemoryPool.hpp b/src/hotspot/share/services/g1MemoryPool.hpp deleted file mode 100644 --- a/src/hotspot/share/services/g1MemoryPool.hpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2007, 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_SERVICES_G1MEMORYPOOL_HPP -#define SHARE_VM_SERVICES_G1MEMORYPOOL_HPP - -#include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS -#include "gc/g1/g1MonitoringSupport.hpp" -#include "services/memoryPool.hpp" -#include "services/memoryUsage.hpp" -#endif // INCLUDE_ALL_GCS - -// This file contains the three classes that represent the memory -// pools of the G1 spaces: G1EdenPool, G1SurvivorPool, and -// G1OldGenPool. In G1, unlike our other GCs, we do not have a -// physical space for each of those spaces. Instead, we allocate -// regions for all three spaces out of a single pool of regions (that -// pool basically covers the entire heap). As a result, the eden, -// survivor, and old gen are considered logical spaces in G1, as each -// is a set of non-contiguous regions. This is also reflected in the -// way we map them to memory pools here. The easiest way to have done -// this would have been to map the entire G1 heap to a single memory -// pool. However, it's helpful to show how large the eden and survivor -// get, as this does affect the performance and behavior of G1. Which -// is why we introduce the three memory pools implemented here. -// -// See comments in g1MonitoringSupport.hpp for additional details -// on this model. -// - -// This class is shared by the three G1 memory pool classes -// (G1EdenPool, G1SurvivorPool, G1OldGenPool). -class G1MemoryPoolSuper : public CollectedMemoryPool { -protected: - const static size_t _undefined_max = (size_t) -1; - G1MonitoringSupport* _g1mm; - - // Would only be called from subclasses. - G1MemoryPoolSuper(G1CollectedHeap* g1h, - const char* name, - size_t init_size, - size_t max_size, - bool support_usage_threshold); -}; - -// Memory pool that represents the G1 eden. -class G1EdenPool : public G1MemoryPoolSuper { -public: - G1EdenPool(G1CollectedHeap* g1h); - - size_t used_in_bytes() { - return _g1mm->eden_space_used(); - } - size_t max_size() const { - return _undefined_max; - } - MemoryUsage get_memory_usage(); -}; - -// Memory pool that represents the G1 survivor. -class G1SurvivorPool : public G1MemoryPoolSuper { -public: - G1SurvivorPool(G1CollectedHeap* g1h); - - size_t used_in_bytes() { - return _g1mm->survivor_space_used(); - } - size_t max_size() const { - return _undefined_max; - } - MemoryUsage get_memory_usage(); -}; - -// Memory pool that represents the G1 old gen. -class G1OldGenPool : public G1MemoryPoolSuper { -public: - G1OldGenPool(G1CollectedHeap* g1h); - - size_t used_in_bytes() { - return _g1mm->old_space_used(); - } - size_t max_size() const { - return _g1mm->old_gen_max(); - } - MemoryUsage get_memory_usage(); -}; - -#endif // SHARE_VM_SERVICES_G1MEMORYPOOL_HPP diff --git a/src/hotspot/share/services/memoryManager.cpp b/src/hotspot/share/services/memoryManager.cpp --- a/src/hotspot/share/services/memoryManager.cpp +++ b/src/hotspot/share/services/memoryManager.cpp @@ -37,7 +37,7 @@ #include "services/gcNotifier.hpp" #include "utilities/dtrace.hpp" -MemoryManager::MemoryManager() { +MemoryManager::MemoryManager(const char* name) : _name(name) { _num_pools = 0; (void)const_cast(_memory_mgr_obj = instanceOop(NULL)); } @@ -52,43 +52,11 @@ } MemoryManager* MemoryManager::get_code_cache_memory_manager() { - return (MemoryManager*) new CodeCacheMemoryManager(); + return new MemoryManager("CodeCacheManager"); } MemoryManager* MemoryManager::get_metaspace_memory_manager() { - return (MemoryManager*) new MetaspaceMemoryManager(); -} - -GCMemoryManager* MemoryManager::get_copy_memory_manager() { - return (GCMemoryManager*) new CopyMemoryManager(); -} - -GCMemoryManager* MemoryManager::get_msc_memory_manager() { - return (GCMemoryManager*) new MSCMemoryManager(); -} - -GCMemoryManager* MemoryManager::get_parnew_memory_manager() { - return (GCMemoryManager*) new ParNewMemoryManager(); -} - -GCMemoryManager* MemoryManager::get_cms_memory_manager() { - return (GCMemoryManager*) new CMSMemoryManager(); -} - -GCMemoryManager* MemoryManager::get_psScavenge_memory_manager() { - return (GCMemoryManager*) new PSScavengeMemoryManager(); -} - -GCMemoryManager* MemoryManager::get_psMarkSweep_memory_manager() { - return (GCMemoryManager*) new PSMarkSweepMemoryManager(); -} - -GCMemoryManager* MemoryManager::get_g1YoungGen_memory_manager() { - return (GCMemoryManager*) new G1YoungGenMemoryManager(); -} - -GCMemoryManager* MemoryManager::get_g1OldGen_memory_manager() { - return (GCMemoryManager*) new G1OldGenMemoryManager(); + return new MemoryManager("Metaspace Manager"); } instanceOop MemoryManager::get_memory_manager_instance(TRAPS) { @@ -203,7 +171,8 @@ } -GCMemoryManager::GCMemoryManager() : MemoryManager() { +GCMemoryManager::GCMemoryManager(const char* name, const char* gc_end_message) : + MemoryManager(name), _gc_end_message(gc_end_message) { _num_collections = 0; _last_gc_stat = NULL; _last_gc_lock = new Mutex(Mutex::leaf, "_last_gc_lock", true, @@ -308,9 +277,7 @@ } if (is_notification_enabled()) { - bool isMajorGC = this == MemoryService::get_major_gc_manager(); - GCNotifier::pushNotification(this, isMajorGC ? "end of major GC" : "end of minor GC", - GCCause::to_string(cause)); + GCNotifier::pushNotification(this, _gc_end_message, GCCause::to_string(cause)); } } } diff --git a/src/hotspot/share/services/memoryManager.hpp b/src/hotspot/share/services/memoryManager.hpp --- a/src/hotspot/share/services/memoryManager.hpp +++ b/src/hotspot/share/services/memoryManager.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -52,11 +52,13 @@ MemoryPool* _pools[max_num_pools]; int _num_pools; + const char* _name; + protected: volatile instanceOop _memory_mgr_obj; public: - MemoryManager(); + MemoryManager(const char* name); int num_memory_pools() const { return _num_pools; } MemoryPool* get_memory_pool(int index) { @@ -70,7 +72,8 @@ virtual instanceOop get_memory_manager_instance(TRAPS); virtual bool is_gc_memory_manager() { return false; } - virtual const char* name() = 0; + + const char* name() const { return _name; } // GC support void oops_do(OopClosure* f); @@ -78,29 +81,6 @@ // 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(); - static GCMemoryManager* get_cms_memory_manager(); - static GCMemoryManager* get_psScavenge_memory_manager(); - static GCMemoryManager* get_psMarkSweep_memory_manager(); - static GCMemoryManager* get_g1YoungGen_memory_manager(); - static GCMemoryManager* get_g1OldGen_memory_manager(); -}; - -class CodeCacheMemoryManager : public MemoryManager { -private: -public: - CodeCacheMemoryManager() : MemoryManager() {} - - const char* name() { return "CodeCacheManager"; } -}; - -class MetaspaceMemoryManager : public MemoryManager { -public: - MetaspaceMemoryManager() : MemoryManager() {} - - const char* name() { return "Metaspace Manager"; } }; class GCStatInfo : public ResourceObj { @@ -162,8 +142,9 @@ GCStatInfo* _current_gc_stat; int _num_gc_threads; volatile bool _notification_enabled; + const char* _gc_end_message; public: - GCMemoryManager(); + GCMemoryManager(const char* name, const char* gc_end_message); ~GCMemoryManager(); void initialize_gc_stat_info(); @@ -189,71 +170,4 @@ bool is_notification_enabled() { return _notification_enabled; } }; -// These subclasses of GCMemoryManager are defined to include -// GC-specific information. -// TODO: Add GC-specific information -class CopyMemoryManager : public GCMemoryManager { -private: -public: - CopyMemoryManager() : GCMemoryManager() {} - - const char* name() { return "Copy"; } -}; - -class MSCMemoryManager : public GCMemoryManager { -private: -public: - MSCMemoryManager() : GCMemoryManager() {} - - const char* name() { return "MarkSweepCompact"; } -}; - -class ParNewMemoryManager : public GCMemoryManager { -private: -public: - ParNewMemoryManager() : GCMemoryManager() {} - - const char* name() { return "ParNew"; } -}; - -class CMSMemoryManager : public GCMemoryManager { -private: -public: - CMSMemoryManager() : GCMemoryManager() {} - - const char* name() { return "ConcurrentMarkSweep";} -}; - -class PSScavengeMemoryManager : public GCMemoryManager { -private: -public: - PSScavengeMemoryManager() : GCMemoryManager() {} - - const char* name() { return "PS Scavenge"; } -}; - -class PSMarkSweepMemoryManager : public GCMemoryManager { -private: -public: - PSMarkSweepMemoryManager() : GCMemoryManager() {} - - const char* name() { return "PS MarkSweep"; } -}; - -class G1YoungGenMemoryManager : public GCMemoryManager { -private: -public: - G1YoungGenMemoryManager() : GCMemoryManager() {} - - const char* name() { return "G1 Young Generation"; } -}; - -class G1OldGenMemoryManager : public GCMemoryManager { -private: -public: - G1OldGenMemoryManager() : GCMemoryManager() {} - - const char* name() { return "G1 Old Generation"; } -}; - #endif // SHARE_VM_SERVICES_MEMORYMANAGER_HPP diff --git a/src/hotspot/share/services/memoryPool.cpp b/src/hotspot/share/services/memoryPool.cpp --- a/src/hotspot/share/services/memoryPool.cpp +++ b/src/hotspot/share/services/memoryPool.cpp @@ -25,8 +25,6 @@ #include "precompiled.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" -#include "gc/serial/defNewGeneration.hpp" -#include "gc/shared/space.hpp" #include "memory/metaspace.hpp" #include "oops/oop.inline.hpp" #include "runtime/handles.inline.hpp" @@ -38,9 +36,6 @@ #include "services/memoryPool.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS -#include "gc/cms/compactibleFreeListSpace.hpp" -#endif MemoryPool::MemoryPool(const char* name, PoolType type, @@ -182,95 +177,6 @@ } } -ContiguousSpacePool::ContiguousSpacePool(ContiguousSpace* space, - const char* name, - PoolType type, - size_t max_size, - bool support_usage_threshold) : - CollectedMemoryPool(name, type, space->capacity(), max_size, - support_usage_threshold), _space(space) { -} - -size_t ContiguousSpacePool::used_in_bytes() { - return space()->used(); -} - -MemoryUsage ContiguousSpacePool::get_memory_usage() { - size_t maxSize = (available_for_allocation() ? max_size() : 0); - size_t used = used_in_bytes(); - size_t committed = _space->capacity(); - - return MemoryUsage(initial_size(), used, committed, maxSize); -} - -SurvivorContiguousSpacePool::SurvivorContiguousSpacePool(DefNewGeneration* young_gen, - const char* name, - PoolType type, - size_t max_size, - bool support_usage_threshold) : - CollectedMemoryPool(name, type, young_gen->from()->capacity(), max_size, - support_usage_threshold), _young_gen(young_gen) { -} - -size_t SurvivorContiguousSpacePool::used_in_bytes() { - return _young_gen->from()->used(); -} - -size_t SurvivorContiguousSpacePool::committed_in_bytes() { - return _young_gen->from()->capacity(); -} - -MemoryUsage SurvivorContiguousSpacePool::get_memory_usage() { - size_t maxSize = (available_for_allocation() ? max_size() : 0); - size_t used = used_in_bytes(); - size_t committed = committed_in_bytes(); - - return MemoryUsage(initial_size(), used, committed, maxSize); -} - -#if INCLUDE_ALL_GCS -CompactibleFreeListSpacePool::CompactibleFreeListSpacePool(CompactibleFreeListSpace* space, - const char* name, - PoolType type, - size_t max_size, - bool support_usage_threshold) : - CollectedMemoryPool(name, type, space->capacity(), max_size, - support_usage_threshold), _space(space) { -} - -size_t CompactibleFreeListSpacePool::used_in_bytes() { - return _space->used(); -} - -MemoryUsage CompactibleFreeListSpacePool::get_memory_usage() { - size_t maxSize = (available_for_allocation() ? max_size() : 0); - size_t used = used_in_bytes(); - size_t committed = _space->capacity(); - - return MemoryUsage(initial_size(), used, committed, maxSize); -} -#endif // INCLUDE_ALL_GCS - -GenerationPool::GenerationPool(Generation* gen, - const char* name, - PoolType type, - bool support_usage_threshold) : - CollectedMemoryPool(name, type, gen->capacity(), gen->max_capacity(), - support_usage_threshold), _gen(gen) { -} - -size_t GenerationPool::used_in_bytes() { - return _gen->used(); -} - -MemoryUsage GenerationPool::get_memory_usage() { - size_t used = used_in_bytes(); - size_t committed = _gen->capacity(); - size_t maxSize = (available_for_allocation() ? max_size() : 0); - - return MemoryUsage(initial_size(), used, committed, maxSize); -} - CodeHeapPool::CodeHeapPool(CodeHeap* codeHeap, const char* name, bool support_usage_threshold) : MemoryPool(name, NonHeap, codeHeap->capacity(), codeHeap->max_capacity(), support_usage_threshold, false), _codeHeap(codeHeap) { diff --git a/src/hotspot/share/services/memoryPool.hpp b/src/hotspot/share/services/memoryPool.hpp --- a/src/hotspot/share/services/memoryPool.hpp +++ b/src/hotspot/share/services/memoryPool.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -37,12 +37,8 @@ // both heap and non-heap memory. // Forward declaration -class CompactibleFreeListSpace; -class ContiguousSpace; class MemoryManager; class SensorInfo; -class Generation; -class DefNewGeneration; class ThresholdSupport; class MemoryPool : public CHeapObj { @@ -144,67 +140,11 @@ class CollectedMemoryPool : public MemoryPool { public: - CollectedMemoryPool(const char* name, PoolType type, size_t init_size, size_t max_size, bool support_usage_threshold) : - MemoryPool(name, type, init_size, max_size, support_usage_threshold, true) {}; + CollectedMemoryPool(const char* name, size_t init_size, size_t max_size, bool support_usage_threshold) : + MemoryPool(name, MemoryPool::Heap, init_size, max_size, support_usage_threshold, true) {}; bool is_collected_pool() { return true; } }; -class ContiguousSpacePool : public CollectedMemoryPool { -private: - ContiguousSpace* _space; - -public: - ContiguousSpacePool(ContiguousSpace* space, const char* name, PoolType type, size_t max_size, bool support_usage_threshold); - - ContiguousSpace* space() { return _space; } - MemoryUsage get_memory_usage(); - size_t used_in_bytes(); -}; - -class SurvivorContiguousSpacePool : public CollectedMemoryPool { -private: - DefNewGeneration* _young_gen; - -public: - SurvivorContiguousSpacePool(DefNewGeneration* young_gen, - const char* name, - PoolType type, - size_t max_size, - bool support_usage_threshold); - - MemoryUsage get_memory_usage(); - - size_t used_in_bytes(); - size_t committed_in_bytes(); -}; - -#if INCLUDE_ALL_GCS -class CompactibleFreeListSpacePool : public CollectedMemoryPool { -private: - CompactibleFreeListSpace* _space; -public: - CompactibleFreeListSpacePool(CompactibleFreeListSpace* space, - const char* name, - PoolType type, - size_t max_size, - bool support_usage_threshold); - - MemoryUsage get_memory_usage(); - size_t used_in_bytes(); -}; -#endif // INCLUDE_ALL_GCS - - -class GenerationPool : public CollectedMemoryPool { -private: - Generation* _gen; -public: - GenerationPool(Generation* gen, const char* name, PoolType type, bool support_usage_threshold); - - MemoryUsage get_memory_usage(); - size_t used_in_bytes(); -}; - class CodeHeapPool: public MemoryPool { private: CodeHeap* _codeHeap; diff --git a/src/hotspot/share/services/memoryService.cpp b/src/hotspot/share/services/memoryService.cpp --- a/src/hotspot/share/services/memoryService.cpp +++ b/src/hotspot/share/services/memoryService.cpp @@ -25,13 +25,7 @@ #include "precompiled.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" -#include "gc/parallel/mutableSpace.hpp" -#include "gc/serial/defNewGeneration.hpp" -#include "gc/serial/tenuredGeneration.hpp" -#include "gc/shared/collectorPolicy.hpp" -#include "gc/shared/genCollectedHeap.hpp" -#include "gc/shared/generation.hpp" -#include "gc/shared/generationSpec.hpp" +#include "gc/shared/collectedHeap.hpp" #include "logging/logConfiguration.hpp" #include "memory/heap.hpp" #include "memory/memRegion.hpp" @@ -46,24 +40,12 @@ #include "services/memoryService.hpp" #include "utilities/growableArray.hpp" #include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS -#include "gc/cms/concurrentMarkSweepGeneration.hpp" -#include "gc/cms/parNewGeneration.hpp" -#include "gc/g1/g1CollectedHeap.inline.hpp" -#include "gc/parallel/parallelScavengeHeap.hpp" -#include "gc/parallel/psOldGen.hpp" -#include "gc/parallel/psYoungGen.hpp" -#include "services/g1MemoryPool.hpp" -#include "services/psMemoryPool.hpp" -#endif // INCLUDE_ALL_GCS GrowableArray* MemoryService::_pools_list = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(init_pools_list_size, true); 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; MemoryManager* MemoryService::_code_cache_manager = NULL; GrowableArray* MemoryService::_code_heap_pools = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(init_code_heap_pools_size, true); @@ -84,311 +66,28 @@ } void MemoryService::set_universe_heap(CollectedHeap* heap) { - CollectedHeap::Name kind = heap->kind(); - switch (kind) { - case CollectedHeap::SerialHeap : - case CollectedHeap::CMSHeap : { - add_gen_collected_heap_info(GenCollectedHeap::heap()); - break; - } -#if INCLUDE_ALL_GCS - case CollectedHeap::ParallelScavengeHeap : { - add_parallel_scavenge_heap_info(ParallelScavengeHeap::heap()); - break; - } - case CollectedHeap::G1CollectedHeap : { - add_g1_heap_info(G1CollectedHeap::heap()); - break; - } -#endif // INCLUDE_ALL_GCS - default: { - guarantee(false, "Unrecognized kind of heap"); - } - } + ResourceMark rm; // For internal allocations in GrowableArray. + + GrowableArray gc_mem_pools = heap->memory_pools(); + _pools_list->appendAll(&gc_mem_pools); // set the GC thread count GcThreadCountClosure gctcc; heap->gc_threads_do(&gctcc); int count = gctcc.count(); - if (count > 0) { - _minor_gc_manager->set_num_gc_threads(count); - _major_gc_manager->set_num_gc_threads(count); - } - // All memory pools and memory managers are initialized. - // - _minor_gc_manager->initialize_gc_stat_info(); - _major_gc_manager->initialize_gc_stat_info(); -} + GrowableArray gc_memory_managers = heap->memory_managers(); + for (int i = 0; i < gc_memory_managers.length(); i++) { + GCMemoryManager* gc_manager = gc_memory_managers.at(i); -// Add memory pools for GenCollectedHeap -// This function currently only supports two generations collected heap. -// The collector for GenCollectedHeap will have two memory managers. -void MemoryService::add_gen_collected_heap_info(GenCollectedHeap* heap) { - CollectorPolicy* policy = heap->collector_policy(); - - assert(policy->is_generation_policy(), "Only support two generations"); - GenCollectorPolicy* gen_policy = policy->as_generation_policy(); - if (gen_policy != NULL) { - Generation::Name kind = gen_policy->young_gen_spec()->name(); - switch (kind) { - case Generation::DefNew: - _minor_gc_manager = MemoryManager::get_copy_memory_manager(); - break; -#if INCLUDE_ALL_GCS - case Generation::ParNew: - _minor_gc_manager = MemoryManager::get_parnew_memory_manager(); - break; -#endif // INCLUDE_ALL_GCS - default: - guarantee(false, "Unrecognized generation spec"); - break; + if (count > 0) { + gc_manager->set_num_gc_threads(count); } - if (policy->is_mark_sweep_policy()) { - _major_gc_manager = MemoryManager::get_msc_memory_manager(); -#if INCLUDE_ALL_GCS - } else if (policy->is_concurrent_mark_sweep_policy()) { - _major_gc_manager = MemoryManager::get_cms_memory_manager(); -#endif // INCLUDE_ALL_GCS - } else { - guarantee(false, "Unknown two-gen policy"); - } - } else { - guarantee(false, "Non two-gen policy"); - } - _managers_list->append(_minor_gc_manager); - _managers_list->append(_major_gc_manager); - - add_generation_memory_pool(heap->young_gen(), _major_gc_manager, _minor_gc_manager); - add_generation_memory_pool(heap->old_gen(), _major_gc_manager); -} - -#if INCLUDE_ALL_GCS -// Add memory pools for ParallelScavengeHeap -// This function currently only supports two generations collected heap. -// The collector for ParallelScavengeHeap will have two memory managers. -void MemoryService::add_parallel_scavenge_heap_info(ParallelScavengeHeap* heap) { - // Two managers to keep statistics about _minor_gc_manager and _major_gc_manager GC. - _minor_gc_manager = MemoryManager::get_psScavenge_memory_manager(); - _major_gc_manager = MemoryManager::get_psMarkSweep_memory_manager(); - _managers_list->append(_minor_gc_manager); - _managers_list->append(_major_gc_manager); - - add_psYoung_memory_pool(heap->young_gen(), _major_gc_manager, _minor_gc_manager); - add_psOld_memory_pool(heap->old_gen(), _major_gc_manager); -} - -void MemoryService::add_g1_heap_info(G1CollectedHeap* g1h) { - assert(UseG1GC, "sanity"); - - _minor_gc_manager = MemoryManager::get_g1YoungGen_memory_manager(); - _major_gc_manager = MemoryManager::get_g1OldGen_memory_manager(); - _managers_list->append(_minor_gc_manager); - _managers_list->append(_major_gc_manager); - - add_g1YoungGen_memory_pool(g1h, _major_gc_manager, _minor_gc_manager); - add_g1OldGen_memory_pool(g1h, _major_gc_manager); -} -#endif // INCLUDE_ALL_GCS - -MemoryPool* MemoryService::add_gen(Generation* gen, - const char* name, - bool is_heap, - bool support_usage_threshold) { - - MemoryPool::PoolType type = (is_heap ? MemoryPool::Heap : MemoryPool::NonHeap); - GenerationPool* pool = new GenerationPool(gen, name, type, support_usage_threshold); - _pools_list->append(pool); - return (MemoryPool*) pool; -} - -MemoryPool* MemoryService::add_space(ContiguousSpace* space, - const char* name, - bool is_heap, - size_t max_size, - bool support_usage_threshold) { - MemoryPool::PoolType type = (is_heap ? MemoryPool::Heap : MemoryPool::NonHeap); - ContiguousSpacePool* pool = new ContiguousSpacePool(space, name, type, max_size, support_usage_threshold); - - _pools_list->append(pool); - return (MemoryPool*) pool; -} - -MemoryPool* MemoryService::add_survivor_spaces(DefNewGeneration* young_gen, - const char* name, - bool is_heap, - size_t max_size, - bool support_usage_threshold) { - MemoryPool::PoolType type = (is_heap ? MemoryPool::Heap : MemoryPool::NonHeap); - SurvivorContiguousSpacePool* pool = new SurvivorContiguousSpacePool(young_gen, name, type, max_size, support_usage_threshold); - - _pools_list->append(pool); - return (MemoryPool*) pool; -} - -#if INCLUDE_ALL_GCS -MemoryPool* MemoryService::add_cms_space(CompactibleFreeListSpace* space, - const char* name, - bool is_heap, - size_t max_size, - bool support_usage_threshold) { - MemoryPool::PoolType type = (is_heap ? MemoryPool::Heap : MemoryPool::NonHeap); - CompactibleFreeListSpacePool* pool = new CompactibleFreeListSpacePool(space, name, type, max_size, support_usage_threshold); - _pools_list->append(pool); - return (MemoryPool*) pool; -} -#endif // INCLUDE_ALL_GCS - -// Add memory pool(s) for one generation -void MemoryService::add_generation_memory_pool(Generation* gen, - MemoryManager* major_mgr, - MemoryManager* minor_mgr) { - guarantee(gen != NULL, "No generation for memory pool"); - Generation::Name kind = gen->kind(); - int index = _pools_list->length(); - - switch (kind) { - case Generation::DefNew: { - assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers"); - DefNewGeneration* young_gen = (DefNewGeneration*) gen; - // Add a memory pool for each space and young gen doesn't - // support low memory detection as it is expected to get filled up. - MemoryPool* eden = add_space(young_gen->eden(), - "Eden Space", - true, /* is_heap */ - young_gen->max_eden_size(), - false /* support_usage_threshold */); - MemoryPool* survivor = add_survivor_spaces(young_gen, - "Survivor Space", - true, /* is_heap */ - young_gen->max_survivor_size(), - false /* support_usage_threshold */); - break; - } - -#if INCLUDE_ALL_GCS - case Generation::ParNew: - { - assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers"); - // Add a memory pool for each space and young gen doesn't - // support low memory detection as it is expected to get filled up. - ParNewGeneration* parnew_gen = (ParNewGeneration*) gen; - MemoryPool* eden = add_space(parnew_gen->eden(), - "Par Eden Space", - true /* is_heap */, - parnew_gen->max_eden_size(), - false /* support_usage_threshold */); - MemoryPool* survivor = add_survivor_spaces(parnew_gen, - "Par Survivor Space", - true, /* is_heap */ - parnew_gen->max_survivor_size(), - false /* support_usage_threshold */); - - break; - } -#endif // INCLUDE_ALL_GCS - - case Generation::MarkSweepCompact: { - assert(major_mgr != NULL && minor_mgr == NULL, "Should have only one manager"); - add_gen(gen, - "Tenured Gen", - true, /* is_heap */ - true /* support_usage_threshold */); - break; - } - -#if INCLUDE_ALL_GCS - case Generation::ConcurrentMarkSweep: - { - assert(major_mgr != NULL && minor_mgr == NULL, "Should have only one manager"); - ConcurrentMarkSweepGeneration* cms = (ConcurrentMarkSweepGeneration*) gen; - MemoryPool* pool = add_cms_space(cms->cmsSpace(), - "CMS Old Gen", - true, /* is_heap */ - cms->reserved().byte_size(), - true /* support_usage_threshold */); - break; - } -#endif // INCLUDE_ALL_GCS - - default: - assert(false, "should not reach here"); - // no memory pool added for others - break; - } - - assert(major_mgr != NULL, "Should have at least one manager"); - // Link managers and the memory pools together - for (int i = index; i < _pools_list->length(); i++) { - MemoryPool* pool = _pools_list->at(i); - major_mgr->add_pool(pool); - if (minor_mgr != NULL) { - minor_mgr->add_pool(pool); - } + gc_manager->initialize_gc_stat_info(); + _managers_list->append(gc_manager); } } - -#if INCLUDE_ALL_GCS -void MemoryService::add_psYoung_memory_pool(PSYoungGen* young_gen, MemoryManager* major_mgr, MemoryManager* minor_mgr) { - assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers"); - - // Add a memory pool for each space and young gen doesn't - // support low memory detection as it is expected to get filled up. - EdenMutableSpacePool* eden = new EdenMutableSpacePool(young_gen, - young_gen->eden_space(), - "PS Eden Space", - MemoryPool::Heap, - false /* support_usage_threshold */); - - SurvivorMutableSpacePool* survivor = new SurvivorMutableSpacePool(young_gen, - "PS Survivor Space", - MemoryPool::Heap, - false /* support_usage_threshold */); - - major_mgr->add_pool(eden); - major_mgr->add_pool(survivor); - minor_mgr->add_pool(eden); - minor_mgr->add_pool(survivor); - _pools_list->append(eden); - _pools_list->append(survivor); -} - -void MemoryService::add_psOld_memory_pool(PSOldGen* old_gen, MemoryManager* mgr) { - PSGenerationPool* old_gen_pool = new PSGenerationPool(old_gen, - "PS Old Gen", - MemoryPool::Heap, - true /* support_usage_threshold */); - mgr->add_pool(old_gen_pool); - _pools_list->append(old_gen_pool); -} - -void MemoryService::add_g1YoungGen_memory_pool(G1CollectedHeap* g1h, - MemoryManager* major_mgr, - MemoryManager* minor_mgr) { - assert(major_mgr != NULL && minor_mgr != NULL, "should have two managers"); - - G1EdenPool* eden = new G1EdenPool(g1h); - G1SurvivorPool* survivor = new G1SurvivorPool(g1h); - - major_mgr->add_pool(eden); - major_mgr->add_pool(survivor); - minor_mgr->add_pool(eden); - minor_mgr->add_pool(survivor); - _pools_list->append(eden); - _pools_list->append(survivor); -} - -void MemoryService::add_g1OldGen_memory_pool(G1CollectedHeap* g1h, - MemoryManager* mgr) { - assert(mgr != NULL, "should have one manager"); - - G1OldGenPool* old_gen = new G1OldGenPool(g1h); - mgr->add_pool(old_gen); - _pools_list->append(old_gen); -} -#endif // INCLUDE_ALL_GCS - void MemoryService::add_code_heap_memory_pool(CodeHeap* heap, const char* name) { // Create new memory pool for this heap MemoryPool* code_heap_pool = new CodeHeapPool(heap, name, true /* support_usage_threshold */); @@ -463,18 +162,11 @@ } } -void MemoryService::gc_begin(bool fullGC, bool recordGCBeginTime, +void MemoryService::gc_begin(GCMemoryManager* manager, bool recordGCBeginTime, bool recordAccumulatedGCTime, bool recordPreGCUsage, bool recordPeakUsage) { - GCMemoryManager* mgr; - if (fullGC) { - mgr = _major_gc_manager; - } else { - mgr = _minor_gc_manager; - } - assert(mgr->is_gc_memory_manager(), "Sanity check"); - mgr->gc_begin(recordGCBeginTime, recordPreGCUsage, recordAccumulatedGCTime); + manager->gc_begin(recordGCBeginTime, recordPreGCUsage, recordAccumulatedGCTime); // Track the peak memory usage when GC begins if (recordPeakUsage) { @@ -485,22 +177,13 @@ } } -void MemoryService::gc_end(bool fullGC, bool recordPostGCUsage, +void MemoryService::gc_end(GCMemoryManager* manager, bool recordPostGCUsage, bool recordAccumulatedGCTime, bool recordGCEndTime, bool countCollection, GCCause::Cause cause) { - - GCMemoryManager* mgr; - if (fullGC) { - mgr = (GCMemoryManager*) _major_gc_manager; - } else { - mgr = (GCMemoryManager*) _minor_gc_manager; - } - assert(mgr->is_gc_memory_manager(), "Sanity check"); - // register the GC end statistics and memory usage - mgr->gc_end(recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime, - countCollection, cause); + manager->gc_end(recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime, + countCollection, cause); } void MemoryService::oops_do(OopClosure* f) { @@ -551,36 +234,7 @@ return obj; } -// GC manager type depends on the type of Generation. Depending on the space -// availability and vm options the gc uses major gc manager or minor gc -// manager or both. The type of gc manager depends on the generation kind. -// For DefNew and ParNew generation doing scavenge gc uses minor gc manager (so -// _fullGC is set to false ) and for other generation kinds doing -// mark-sweep-compact uses major gc manager (so _fullGC is set to true). -TraceMemoryManagerStats::TraceMemoryManagerStats(Generation::Name kind, GCCause::Cause cause) { - switch (kind) { - case Generation::DefNew: -#if INCLUDE_ALL_GCS - case Generation::ParNew: -#endif // INCLUDE_ALL_GCS - _fullGC = false; - break; - case Generation::MarkSweepCompact: -#if INCLUDE_ALL_GCS - case Generation::ConcurrentMarkSweep: -#endif // INCLUDE_ALL_GCS - _fullGC = true; - break; - default: - _fullGC = false; - assert(false, "Unrecognized gc generation kind."); - } - // this has to be called in a stop the world pause and represent - // an entire gc pause, start to finish: - initialize(_fullGC, cause, true, true, true, true, true, true, true); -} - -TraceMemoryManagerStats::TraceMemoryManagerStats(bool fullGC, +TraceMemoryManagerStats::TraceMemoryManagerStats(GCMemoryManager* gc_memory_manager, GCCause::Cause cause, bool recordGCBeginTime, bool recordPreGCUsage, @@ -589,14 +243,14 @@ bool recordAccumulatedGCTime, bool recordGCEndTime, bool countCollection) { - initialize(fullGC, cause, recordGCBeginTime, recordPreGCUsage, recordPeakUsage, + initialize(gc_memory_manager, cause, recordGCBeginTime, recordPreGCUsage, recordPeakUsage, recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime, countCollection); } // for a subclass to create then initialize an instance before invoking // the MemoryService -void TraceMemoryManagerStats::initialize(bool fullGC, +void TraceMemoryManagerStats::initialize(GCMemoryManager* gc_memory_manager, GCCause::Cause cause, bool recordGCBeginTime, bool recordPreGCUsage, @@ -605,7 +259,7 @@ bool recordAccumulatedGCTime, bool recordGCEndTime, bool countCollection) { - _fullGC = fullGC; + _gc_memory_manager = gc_memory_manager; _recordGCBeginTime = recordGCBeginTime; _recordPreGCUsage = recordPreGCUsage; _recordPeakUsage = recordPeakUsage; @@ -615,11 +269,11 @@ _countCollection = countCollection; _cause = cause; - MemoryService::gc_begin(_fullGC, _recordGCBeginTime, _recordAccumulatedGCTime, + MemoryService::gc_begin(_gc_memory_manager, _recordGCBeginTime, _recordAccumulatedGCTime, _recordPreGCUsage, _recordPeakUsage); } TraceMemoryManagerStats::~TraceMemoryManagerStats() { - MemoryService::gc_end(_fullGC, _recordPostGCUsage, _recordAccumulatedGCTime, + MemoryService::gc_end(_gc_memory_manager, _recordPostGCUsage, _recordAccumulatedGCTime, _recordGCEndTime, _countCollection, _cause); } diff --git a/src/hotspot/share/services/memoryService.hpp b/src/hotspot/share/services/memoryService.hpp --- a/src/hotspot/share/services/memoryService.hpp +++ b/src/hotspot/share/services/memoryService.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -26,7 +26,6 @@ #define SHARE_VM_SERVICES_MEMORYSERVICE_HPP #include "gc/shared/gcCause.hpp" -#include "gc/shared/generation.hpp" #include "logging/log.hpp" #include "memory/allocation.hpp" #include "runtime/handles.hpp" @@ -37,16 +36,7 @@ class MemoryManager; class GCMemoryManager; class CollectedHeap; -class Generation; -class DefNewGeneration; -class PSYoungGen; -class PSOldGen; class CodeHeap; -class ContiguousSpace; -class CompactibleFreeListSpace; -class GenCollectedHeap; -class ParallelScavengeHeap; -class G1CollectedHeap; // VM Monitoring and Management Support @@ -61,10 +51,6 @@ static GrowableArray* _pools_list; static GrowableArray* _managers_list; - // memory managers for minor and major GC statistics - static GCMemoryManager* _major_gc_manager; - static GCMemoryManager* _minor_gc_manager; - // memory manager and code heap pools for the CodeCache static MemoryManager* _code_cache_manager; static GrowableArray* _code_heap_pools; @@ -72,51 +58,6 @@ static MemoryPool* _metaspace_pool; static MemoryPool* _compressed_class_pool; - static void add_generation_memory_pool(Generation* gen, - MemoryManager* major_mgr, - MemoryManager* minor_mgr); - static void add_generation_memory_pool(Generation* gen, - MemoryManager* major_mgr) { - add_generation_memory_pool(gen, major_mgr, NULL); - } - - - static void add_psYoung_memory_pool(PSYoungGen* young_gen, - MemoryManager* major_mgr, - MemoryManager* minor_mgr); - static void add_psOld_memory_pool(PSOldGen* old_gen, - MemoryManager* mgr); - - static void add_g1YoungGen_memory_pool(G1CollectedHeap* g1h, - MemoryManager* major_mgr, - MemoryManager* minor_mgr); - static void add_g1OldGen_memory_pool(G1CollectedHeap* g1h, - MemoryManager* mgr); - - static MemoryPool* add_space(ContiguousSpace* space, - const char* name, - bool is_heap, - size_t max_size, - bool support_usage_threshold); - static MemoryPool* add_survivor_spaces(DefNewGeneration* young_gen, - const char* name, - bool is_heap, - size_t max_size, - bool support_usage_threshold); - static MemoryPool* add_gen(Generation* gen, - const char* name, - bool is_heap, - bool support_usage_threshold); - static MemoryPool* add_cms_space(CompactibleFreeListSpace* space, - const char* name, - bool is_heap, - size_t max_size, - bool support_usage_threshold); - - static void add_gen_collected_heap_info(GenCollectedHeap* heap); - static void add_parallel_scavenge_heap_info(ParallelScavengeHeap* heap); - static void add_g1_heap_info(G1CollectedHeap* g1h); - public: static void set_universe_heap(CollectedHeap* heap); static void add_code_heap_memory_pool(CodeHeap* heap, const char* name); @@ -155,10 +96,10 @@ } static void track_memory_pool_usage(MemoryPool* pool); - static void gc_begin(bool fullGC, bool recordGCBeginTime, + static void gc_begin(GCMemoryManager* manager, bool recordGCBeginTime, bool recordAccumulatedGCTime, bool recordPreGCUsage, bool recordPeakUsage); - static void gc_end(bool fullGC, bool recordPostGCUsage, + static void gc_end(GCMemoryManager* manager, bool recordPostGCUsage, bool recordAccumulatedGCTime, bool recordGCEndTime, bool countCollection, GCCause::Cause cause); @@ -170,19 +111,11 @@ // Create an instance of java/lang/management/MemoryUsage static Handle create_MemoryUsage_obj(MemoryUsage usage, TRAPS); - - static const GCMemoryManager* get_minor_gc_manager() { - return _minor_gc_manager; - } - - static const GCMemoryManager* get_major_gc_manager() { - return _major_gc_manager; - } }; class TraceMemoryManagerStats : public StackObj { private: - bool _fullGC; + GCMemoryManager* _gc_memory_manager; bool _recordGCBeginTime; bool _recordPreGCUsage; bool _recordPeakUsage; @@ -193,7 +126,7 @@ GCCause::Cause _cause; public: TraceMemoryManagerStats() {} - TraceMemoryManagerStats(bool fullGC, + TraceMemoryManagerStats(GCMemoryManager* gc_memory_manager, GCCause::Cause cause, bool recordGCBeginTime = true, bool recordPreGCUsage = true, @@ -203,7 +136,7 @@ bool recordGCEndTime = true, bool countCollection = true); - void initialize(bool fullGC, + void initialize(GCMemoryManager* gc_memory_manager, GCCause::Cause cause, bool recordGCBeginTime, bool recordPreGCUsage, @@ -213,7 +146,6 @@ bool recordGCEndTime, bool countCollection); - TraceMemoryManagerStats(Generation::Name kind, GCCause::Cause cause); ~TraceMemoryManagerStats(); }; diff --git a/src/hotspot/share/services/psMemoryPool.cpp b/src/hotspot/share/services/psMemoryPool.cpp deleted file mode 100644 --- a/src/hotspot/share/services/psMemoryPool.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2007, 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. - * - */ - -#include "precompiled.hpp" -#include "classfile/systemDictionary.hpp" -#include "classfile/vmSymbols.hpp" -#include "oops/oop.inline.hpp" -#include "runtime/handles.inline.hpp" -#include "runtime/javaCalls.hpp" -#include "services/lowMemoryDetector.hpp" -#include "services/management.hpp" -#include "services/memoryManager.hpp" -#include "services/psMemoryPool.hpp" - -PSGenerationPool::PSGenerationPool(PSOldGen* old_gen, - const char* name, - PoolType type, - bool support_usage_threshold) : - CollectedMemoryPool(name, type, old_gen->capacity_in_bytes(), - old_gen->reserved().byte_size(), support_usage_threshold), _old_gen(old_gen) { -} - -MemoryUsage PSGenerationPool::get_memory_usage() { - size_t maxSize = (available_for_allocation() ? max_size() : 0); - size_t used = used_in_bytes(); - size_t committed = _old_gen->capacity_in_bytes(); - - return MemoryUsage(initial_size(), used, committed, maxSize); -} - -// The max size of EdenMutableSpacePool = -// max size of the PSYoungGen - capacity of two survivor spaces -// -// Max size of PS eden space is changing due to ergonomic. -// PSYoungGen, PSOldGen, Eden, Survivor spaces are all resizable. -// -EdenMutableSpacePool::EdenMutableSpacePool(PSYoungGen* young_gen, - MutableSpace* space, - const char* name, - PoolType type, - bool support_usage_threshold) : - CollectedMemoryPool(name, type, space->capacity_in_bytes(), - (young_gen->max_size() - young_gen->from_space()->capacity_in_bytes() - young_gen->to_space()->capacity_in_bytes()), - support_usage_threshold), - _young_gen(young_gen), - _space(space) { -} - -MemoryUsage EdenMutableSpacePool::get_memory_usage() { - size_t maxSize = (available_for_allocation() ? max_size() : 0); - size_t used = used_in_bytes(); - size_t committed = _space->capacity_in_bytes(); - - return MemoryUsage(initial_size(), used, committed, maxSize); -} - -// The max size of SurvivorMutableSpacePool = -// current capacity of the from-space -// -// PS from and to survivor spaces could have different sizes. -// -SurvivorMutableSpacePool::SurvivorMutableSpacePool(PSYoungGen* young_gen, - const char* name, - PoolType type, - bool support_usage_threshold) : - CollectedMemoryPool(name, type, young_gen->from_space()->capacity_in_bytes(), - young_gen->from_space()->capacity_in_bytes(), - support_usage_threshold), _young_gen(young_gen) { -} - -MemoryUsage SurvivorMutableSpacePool::get_memory_usage() { - size_t maxSize = (available_for_allocation() ? max_size() : 0); - size_t used = used_in_bytes(); - size_t committed = committed_in_bytes(); - return MemoryUsage(initial_size(), used, committed, maxSize); -} diff --git a/src/hotspot/share/services/psMemoryPool.hpp b/src/hotspot/share/services/psMemoryPool.hpp deleted file mode 100644 --- a/src/hotspot/share/services/psMemoryPool.hpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2007, 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_SERVICES_PSMEMORYPOOL_HPP -#define SHARE_VM_SERVICES_PSMEMORYPOOL_HPP - -#include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS -#include "gc/parallel/mutableSpace.hpp" -#include "gc/parallel/psOldGen.hpp" -#include "gc/parallel/psYoungGen.hpp" -#include "gc/serial/defNewGeneration.hpp" -#include "gc/shared/space.hpp" -#include "memory/heap.hpp" -#include "services/memoryPool.hpp" -#include "services/memoryUsage.hpp" -#endif // INCLUDE_ALL_GCS - -class PSGenerationPool : public CollectedMemoryPool { -private: - PSOldGen* _old_gen; - -public: - PSGenerationPool(PSOldGen* pool, const char* name, PoolType type, bool support_usage_threshold); - - MemoryUsage get_memory_usage(); - size_t used_in_bytes() { return _old_gen->used_in_bytes(); } - size_t max_size() const { return _old_gen->reserved().byte_size(); } -}; - -class EdenMutableSpacePool : public CollectedMemoryPool { -private: - PSYoungGen* _young_gen; - MutableSpace* _space; - -public: - EdenMutableSpacePool(PSYoungGen* young_gen, - MutableSpace* space, - const char* name, - PoolType type, - bool support_usage_threshold); - - MutableSpace* space() { return _space; } - MemoryUsage get_memory_usage(); - size_t used_in_bytes() { return space()->used_in_bytes(); } - size_t max_size() const { - // Eden's max_size = max_size of Young Gen - the current committed size of survivor spaces - return _young_gen->max_size() - _young_gen->from_space()->capacity_in_bytes() - _young_gen->to_space()->capacity_in_bytes(); - } -}; - -class SurvivorMutableSpacePool : public CollectedMemoryPool { -private: - PSYoungGen* _young_gen; - -public: - SurvivorMutableSpacePool(PSYoungGen* young_gen, - const char* name, - PoolType type, - bool support_usage_threshold); - - MemoryUsage get_memory_usage(); - - size_t used_in_bytes() { - return _young_gen->from_space()->used_in_bytes(); - } - size_t committed_in_bytes() { - return _young_gen->from_space()->capacity_in_bytes(); - } - size_t max_size() const { - // Return current committed size of the from-space - return _young_gen->from_space()->capacity_in_bytes(); - } -}; - -#endif // SHARE_VM_SERVICES_PSMEMORYPOOL_HPP diff --git a/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java b/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java new file mode 100644 --- /dev/null +++ b/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java @@ -0,0 +1,100 @@ +/* + * 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.List; +import java.util.ArrayList; +import java.lang.management.*; +import static jdk.test.lib.Asserts.*; +import java.util.stream.*; + +/* @test TestMemoryMXBeansAndPoolsPresence + * @bug 8191564 + * @summary Tests that GarbageCollectorMXBeans and GC MemoryPools are created. + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @run main/othervm -XX:+UseG1GC TestMemoryMXBeansAndPoolsPresence G1 + * @run main/othervm -XX:+UseConcMarkSweepGC TestMemoryMXBeansAndPoolsPresence CMS + * @run main/othervm -XX:+UseParallelGC TestMemoryMXBeansAndPoolsPresence Parallel + * @run main/othervm -XX:+UseSerialGC TestMemoryMXBeansAndPoolsPresence Serial + */ + +class GCBeanDescription { + public String name; + public String[] poolNames; + + public GCBeanDescription(String name, String[] poolNames) { + this.name = name; + this.poolNames = poolNames; + } +} + +public class TestMemoryMXBeansAndPoolsPresence { + public static void test(GCBeanDescription... expectedBeans) { + List memoryPools = ManagementFactory.getMemoryPoolMXBeans(); + + List gcBeans = ManagementFactory.getGarbageCollectorMXBeans(); + assertEQ(expectedBeans.length, gcBeans.size()); + + for (GCBeanDescription desc : expectedBeans) { + List beans = gcBeans.stream() + .filter(b -> b.getName().equals(desc.name)) + .collect(Collectors.toList()); + assertEQ(beans.size(), 1); + + GarbageCollectorMXBean bean = beans.get(0); + assertEQ(desc.name, bean.getName()); + + String[] pools = bean.getMemoryPoolNames(); + assertEQ(desc.poolNames.length, pools.length); + for (int i = 0; i < desc.poolNames.length; i++) { + assertEQ(desc.poolNames[i], pools[i]); + } + } + } + + public static void main(String[] args) { + switch (args[0]) { + case "G1": + test(new GCBeanDescription("G1 Young Generation", new String[] {"G1 Eden Space", "G1 Survivor Space"}), + new GCBeanDescription("G1 Old Generation", new String[] {"G1 Eden Space", "G1 Survivor Space", "G1 Old Gen"})); + break; + case "CMS": + test(new GCBeanDescription("ParNew", new String[] {"Par Eden Space", "Par Survivor Space"}), + new GCBeanDescription("ConcurrentMarkSweep", new String[] {"Par Eden Space", "Par Survivor Space", "CMS Old Gen"})); + break; + case "Parallel": + test(new GCBeanDescription("PS Scavenge", new String[] {"PS Eden Space", "PS Survivor Space"}), + new GCBeanDescription("PS MarkSweep", new String[] {"PS Eden Space", "PS Survivor Space", "PS Old Gen"})); + break; + case "Serial": + test(new GCBeanDescription("Copy", new String[] {"Eden Space", "Survivor Space"}), + new GCBeanDescription("MarkSweepCompact", new String[] {"Eden Space", "Survivor Space", "Tenured Gen"})); + break; + default: + assertTrue(false); + break; + + } + } +}