Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/services/memoryService.cpp
32285 views
/*1* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "classfile/systemDictionary.hpp"26#include "classfile/vmSymbols.hpp"27#include "gc_implementation/shared/mutableSpace.hpp"28#include "memory/collectorPolicy.hpp"29#include "memory/defNewGeneration.hpp"30#include "memory/genCollectedHeap.hpp"31#include "memory/generation.hpp"32#include "memory/generationSpec.hpp"33#include "memory/heap.hpp"34#include "memory/memRegion.hpp"35#include "memory/tenuredGeneration.hpp"36#include "oops/oop.inline.hpp"37#include "runtime/globals.hpp"38#include "runtime/javaCalls.hpp"39#include "services/classLoadingService.hpp"40#include "services/lowMemoryDetector.hpp"41#include "services/management.hpp"42#include "services/memoryManager.hpp"43#include "services/memoryPool.hpp"44#include "services/memoryService.hpp"45#include "utilities/growableArray.hpp"46#include "utilities/macros.hpp"47#if INCLUDE_ALL_GCS48#include "gc_implementation/shenandoah/shenandoahHeap.inline.hpp"49#include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp"50#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"51#include "gc_implementation/parNew/parNewGeneration.hpp"52#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"53#include "gc_implementation/parallelScavenge/psOldGen.hpp"54#include "gc_implementation/parallelScavenge/psYoungGen.hpp"55#include "services/g1MemoryPool.hpp"56#include "services/psMemoryPool.hpp"57#include "services/shenandoahMemoryPool.hpp"58#endif // INCLUDE_ALL_GCS5960GrowableArray<MemoryPool*>* MemoryService::_pools_list =61new (ResourceObj::C_HEAP, mtInternal) GrowableArray<MemoryPool*>(init_pools_list_size, true);62GrowableArray<MemoryManager*>* MemoryService::_managers_list =63new (ResourceObj::C_HEAP, mtInternal) GrowableArray<MemoryManager*>(init_managers_list_size, true);6465GCMemoryManager* MemoryService::_minor_gc_manager = NULL;66GCMemoryManager* MemoryService::_major_gc_manager = NULL;67MemoryPool* MemoryService::_code_heap_pool = NULL;68MemoryPool* MemoryService::_metaspace_pool = NULL;69MemoryPool* MemoryService::_compressed_class_pool = NULL;7071class GcThreadCountClosure: public ThreadClosure {72private:73int _count;74public:75GcThreadCountClosure() : _count(0) {};76void do_thread(Thread* thread);77int count() { return _count; }78};7980void GcThreadCountClosure::do_thread(Thread* thread) {81_count++;82}8384void MemoryService::set_universe_heap(CollectedHeap* heap) {85CollectedHeap::Name kind = heap->kind();86switch (kind) {87case CollectedHeap::GenCollectedHeap : {88add_gen_collected_heap_info(GenCollectedHeap::heap());89break;90}91#if INCLUDE_ALL_GCS92case CollectedHeap::ParallelScavengeHeap : {93add_parallel_scavenge_heap_info(ParallelScavengeHeap::heap());94break;95}96case CollectedHeap::G1CollectedHeap : {97add_g1_heap_info(G1CollectedHeap::heap());98break;99}100case CollectedHeap::ShenandoahHeap : {101add_shenandoah_heap_info(ShenandoahHeap::heap());102break;103}104#endif // INCLUDE_ALL_GCS105default: {106guarantee(false, "Unrecognized kind of heap");107}108}109110// set the GC thread count111GcThreadCountClosure gctcc;112heap->gc_threads_do(&gctcc);113int count = gctcc.count();114if (count > 0) {115_minor_gc_manager->set_num_gc_threads(count);116_major_gc_manager->set_num_gc_threads(count);117}118119// All memory pools and memory managers are initialized.120//121_minor_gc_manager->initialize_gc_stat_info();122_major_gc_manager->initialize_gc_stat_info();123}124125// Add memory pools for GenCollectedHeap126// This function currently only supports two generations collected heap.127// The collector for GenCollectedHeap will have two memory managers.128void MemoryService::add_gen_collected_heap_info(GenCollectedHeap* heap) {129CollectorPolicy* policy = heap->collector_policy();130131assert(policy->is_two_generation_policy(), "Only support two generations");132guarantee(heap->n_gens() == 2, "Only support two-generation heap");133134TwoGenerationCollectorPolicy* two_gen_policy = policy->as_two_generation_policy();135if (two_gen_policy != NULL) {136GenerationSpec** specs = two_gen_policy->generations();137Generation::Name kind = specs[0]->name();138switch (kind) {139case Generation::DefNew:140_minor_gc_manager = MemoryManager::get_copy_memory_manager();141break;142#if INCLUDE_ALL_GCS143case Generation::ParNew:144case Generation::ASParNew:145_minor_gc_manager = MemoryManager::get_parnew_memory_manager();146break;147#endif // INCLUDE_ALL_GCS148default:149guarantee(false, "Unrecognized generation spec");150break;151}152if (policy->is_mark_sweep_policy()) {153_major_gc_manager = MemoryManager::get_msc_memory_manager();154#if INCLUDE_ALL_GCS155} else if (policy->is_concurrent_mark_sweep_policy()) {156_major_gc_manager = MemoryManager::get_cms_memory_manager();157#endif // INCLUDE_ALL_GCS158} else {159guarantee(false, "Unknown two-gen policy");160}161} else {162guarantee(false, "Non two-gen policy");163}164_managers_list->append(_minor_gc_manager);165_managers_list->append(_major_gc_manager);166167add_generation_memory_pool(heap->get_gen(minor), _major_gc_manager, _minor_gc_manager);168add_generation_memory_pool(heap->get_gen(major), _major_gc_manager);169}170171#if INCLUDE_ALL_GCS172// Add memory pools for ParallelScavengeHeap173// This function currently only supports two generations collected heap.174// The collector for ParallelScavengeHeap will have two memory managers.175void MemoryService::add_parallel_scavenge_heap_info(ParallelScavengeHeap* heap) {176// Two managers to keep statistics about _minor_gc_manager and _major_gc_manager GC.177_minor_gc_manager = MemoryManager::get_psScavenge_memory_manager();178_major_gc_manager = MemoryManager::get_psMarkSweep_memory_manager();179_managers_list->append(_minor_gc_manager);180_managers_list->append(_major_gc_manager);181182add_psYoung_memory_pool(heap->young_gen(), _major_gc_manager, _minor_gc_manager);183add_psOld_memory_pool(heap->old_gen(), _major_gc_manager);184}185186void MemoryService::add_g1_heap_info(G1CollectedHeap* g1h) {187assert(UseG1GC, "sanity");188189_minor_gc_manager = MemoryManager::get_g1YoungGen_memory_manager();190_major_gc_manager = MemoryManager::get_g1OldGen_memory_manager();191_managers_list->append(_minor_gc_manager);192_managers_list->append(_major_gc_manager);193194add_g1YoungGen_memory_pool(g1h, _major_gc_manager, _minor_gc_manager);195add_g1OldGen_memory_pool(g1h, _major_gc_manager, _minor_gc_manager);196}197198void MemoryService::add_shenandoah_heap_info(ShenandoahHeap* heap) {199assert(UseShenandoahGC, "sanity");200201// We reuse the "minor/major" names, even though they make little sense202// in Shenandoah. JDK 10+ makes this right, but not JDK 9-.203_major_gc_manager = MemoryManager::get_shenandoah_pauses_memory_manager();204_minor_gc_manager = MemoryManager::get_shenandoah_cycles_memory_manager();205_managers_list->append(_major_gc_manager);206_managers_list->append(_minor_gc_manager);207208ShenandoahMemoryPool* pool = new ShenandoahMemoryPool(heap);209_pools_list->append(pool);210211_major_gc_manager->add_pool(pool);212_minor_gc_manager->add_pool(pool);213}214215#endif // INCLUDE_ALL_GCS216217MemoryPool* MemoryService::add_gen(Generation* gen,218const char* name,219bool is_heap,220bool support_usage_threshold) {221222MemoryPool::PoolType type = (is_heap ? MemoryPool::Heap : MemoryPool::NonHeap);223GenerationPool* pool = new GenerationPool(gen, name, type, support_usage_threshold);224_pools_list->append(pool);225return (MemoryPool*) pool;226}227228MemoryPool* MemoryService::add_space(ContiguousSpace* space,229const char* name,230bool is_heap,231size_t max_size,232bool support_usage_threshold) {233MemoryPool::PoolType type = (is_heap ? MemoryPool::Heap : MemoryPool::NonHeap);234ContiguousSpacePool* pool = new ContiguousSpacePool(space, name, type, max_size, support_usage_threshold);235236_pools_list->append(pool);237return (MemoryPool*) pool;238}239240MemoryPool* MemoryService::add_survivor_spaces(DefNewGeneration* gen,241const char* name,242bool is_heap,243size_t max_size,244bool support_usage_threshold) {245MemoryPool::PoolType type = (is_heap ? MemoryPool::Heap : MemoryPool::NonHeap);246SurvivorContiguousSpacePool* pool = new SurvivorContiguousSpacePool(gen, name, type, max_size, support_usage_threshold);247248_pools_list->append(pool);249return (MemoryPool*) pool;250}251252#if INCLUDE_ALL_GCS253MemoryPool* MemoryService::add_cms_space(CompactibleFreeListSpace* space,254const char* name,255bool is_heap,256size_t max_size,257bool support_usage_threshold) {258MemoryPool::PoolType type = (is_heap ? MemoryPool::Heap : MemoryPool::NonHeap);259CompactibleFreeListSpacePool* pool = new CompactibleFreeListSpacePool(space, name, type, max_size, support_usage_threshold);260_pools_list->append(pool);261return (MemoryPool*) pool;262}263#endif // INCLUDE_ALL_GCS264265// Add memory pool(s) for one generation266void MemoryService::add_generation_memory_pool(Generation* gen,267GCMemoryManager* major_mgr,268GCMemoryManager* minor_mgr) {269guarantee(gen != NULL, "No generation for memory pool");270Generation::Name kind = gen->kind();271int index = _pools_list->length();272273switch (kind) {274case Generation::DefNew: {275assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers");276DefNewGeneration* young_gen = (DefNewGeneration*) gen;277// Add a memory pool for each space and young gen doesn't278// support low memory detection as it is expected to get filled up.279MemoryPool* eden = add_space(young_gen->eden(),280"Eden Space",281true, /* is_heap */282young_gen->max_eden_size(),283false /* support_usage_threshold */);284MemoryPool* survivor = add_survivor_spaces(young_gen,285"Survivor Space",286true, /* is_heap */287young_gen->max_survivor_size(),288false /* support_usage_threshold */);289break;290}291292#if INCLUDE_ALL_GCS293case Generation::ParNew:294case Generation::ASParNew:295{296assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers");297// Add a memory pool for each space and young gen doesn't298// support low memory detection as it is expected to get filled up.299ParNewGeneration* parnew_gen = (ParNewGeneration*) gen;300MemoryPool* eden = add_space(parnew_gen->eden(),301"Par Eden Space",302true /* is_heap */,303parnew_gen->max_eden_size(),304false /* support_usage_threshold */);305MemoryPool* survivor = add_survivor_spaces(parnew_gen,306"Par Survivor Space",307true, /* is_heap */308parnew_gen->max_survivor_size(),309false /* support_usage_threshold */);310311break;312}313#endif // INCLUDE_ALL_GCS314315case Generation::MarkSweepCompact: {316assert(major_mgr != NULL && minor_mgr == NULL, "Should have only one manager");317add_gen(gen,318"Tenured Gen",319true, /* is_heap */320true /* support_usage_threshold */);321break;322}323324#if INCLUDE_ALL_GCS325case Generation::ConcurrentMarkSweep:326case Generation::ASConcurrentMarkSweep:327{328assert(major_mgr != NULL && minor_mgr == NULL, "Should have only one manager");329ConcurrentMarkSweepGeneration* cms = (ConcurrentMarkSweepGeneration*) gen;330MemoryPool* pool = add_cms_space(cms->cmsSpace(),331"CMS Old Gen",332true, /* is_heap */333cms->reserved().byte_size(),334true /* support_usage_threshold */);335break;336}337#endif // INCLUDE_ALL_GCS338339default:340assert(false, "should not reach here");341// no memory pool added for others342break;343}344345assert(major_mgr != NULL, "Should have at least one manager");346// Link managers and the memory pools together347for (int i = index; i < _pools_list->length(); i++) {348MemoryPool* pool = _pools_list->at(i);349major_mgr->add_pool(pool);350if (minor_mgr != NULL) {351minor_mgr->add_pool(pool);352}353}354}355356357#if INCLUDE_ALL_GCS358void MemoryService::add_psYoung_memory_pool(PSYoungGen* gen,359GCMemoryManager* major_mgr,360GCMemoryManager* minor_mgr) {361assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers");362363// Add a memory pool for each space and young gen doesn't364// support low memory detection as it is expected to get filled up.365EdenMutableSpacePool* eden = new EdenMutableSpacePool(gen,366gen->eden_space(),367"PS Eden Space",368MemoryPool::Heap,369false /* support_usage_threshold */);370371SurvivorMutableSpacePool* survivor = new SurvivorMutableSpacePool(gen,372"PS Survivor Space",373MemoryPool::Heap,374false /* support_usage_threshold */);375376major_mgr->add_pool(eden);377major_mgr->add_pool(survivor);378minor_mgr->add_pool(eden);379minor_mgr->add_pool(survivor);380_pools_list->append(eden);381_pools_list->append(survivor);382}383384void MemoryService::add_psOld_memory_pool(PSOldGen* gen, GCMemoryManager* mgr) {385PSGenerationPool* old_gen = new PSGenerationPool(gen,386"PS Old Gen",387MemoryPool::Heap,388true /* support_usage_threshold */);389mgr->add_pool(old_gen);390_pools_list->append(old_gen);391}392393void MemoryService::add_g1YoungGen_memory_pool(G1CollectedHeap* g1h,394GCMemoryManager* major_mgr,395GCMemoryManager* minor_mgr) {396assert(major_mgr != NULL && minor_mgr != NULL, "should have two managers");397398G1EdenPool* eden = new G1EdenPool(g1h);399G1SurvivorPool* survivor = new G1SurvivorPool(g1h);400401major_mgr->add_pool(eden);402major_mgr->add_pool(survivor);403minor_mgr->add_pool(eden);404minor_mgr->add_pool(survivor);405_pools_list->append(eden);406_pools_list->append(survivor);407}408409void MemoryService::add_g1OldGen_memory_pool(G1CollectedHeap* g1h,410GCMemoryManager* major_mgr,411GCMemoryManager* minor_mgr) {412assert(major_mgr != NULL && minor_mgr != NULL, "should have two managers");413414G1OldGenPool* old_gen = new G1OldGenPool(g1h);415major_mgr->add_pool(old_gen);416minor_mgr->add_pool(old_gen, false /* always_affected_by_gc */);417_pools_list->append(old_gen);418}419#endif // INCLUDE_ALL_GCS420421void MemoryService::add_code_heap_memory_pool(CodeHeap* heap) {422_code_heap_pool = new CodeHeapPool(heap,423"Code Cache",424true /* support_usage_threshold */);425MemoryManager* mgr = MemoryManager::get_code_cache_memory_manager();426mgr->add_pool(_code_heap_pool);427428_pools_list->append(_code_heap_pool);429_managers_list->append(mgr);430}431432void MemoryService::add_metaspace_memory_pools() {433MemoryManager* mgr = MemoryManager::get_metaspace_memory_manager();434435_metaspace_pool = new MetaspacePool();436mgr->add_pool(_metaspace_pool);437_pools_list->append(_metaspace_pool);438439if (UseCompressedClassPointers) {440_compressed_class_pool = new CompressedKlassSpacePool();441mgr->add_pool(_compressed_class_pool);442_pools_list->append(_compressed_class_pool);443}444445_managers_list->append(mgr);446}447448MemoryManager* MemoryService::get_memory_manager(instanceHandle mh) {449for (int i = 0; i < _managers_list->length(); i++) {450MemoryManager* mgr = _managers_list->at(i);451if (mgr->is_manager(mh)) {452return mgr;453}454}455return NULL;456}457458MemoryPool* MemoryService::get_memory_pool(instanceHandle ph) {459for (int i = 0; i < _pools_list->length(); i++) {460MemoryPool* pool = _pools_list->at(i);461if (pool->is_pool(ph)) {462return pool;463}464}465return NULL;466}467468void MemoryService::track_memory_usage() {469// Track the peak memory usage470for (int i = 0; i < _pools_list->length(); i++) {471MemoryPool* pool = _pools_list->at(i);472pool->record_peak_memory_usage();473}474475// Detect low memory476LowMemoryDetector::detect_low_memory();477}478479void MemoryService::track_memory_pool_usage(MemoryPool* pool) {480// Track the peak memory usage481pool->record_peak_memory_usage();482483// Detect low memory484if (LowMemoryDetector::is_enabled(pool)) {485LowMemoryDetector::detect_low_memory(pool);486}487}488489void MemoryService::gc_begin(bool fullGC, bool recordGCBeginTime,490bool recordAccumulatedGCTime,491bool recordPreGCUsage, bool recordPeakUsage) {492493GCMemoryManager* mgr;494if (fullGC) {495mgr = _major_gc_manager;496} else {497mgr = _minor_gc_manager;498}499assert(mgr->is_gc_memory_manager(), "Sanity check");500mgr->gc_begin(recordGCBeginTime, recordPreGCUsage, recordAccumulatedGCTime);501502// Track the peak memory usage when GC begins503if (recordPeakUsage) {504for (int i = 0; i < _pools_list->length(); i++) {505MemoryPool* pool = _pools_list->at(i);506pool->record_peak_memory_usage();507}508}509}510511void MemoryService::gc_end(bool fullGC, bool recordPostGCUsage,512bool recordAccumulatedGCTime,513bool recordGCEndTime, bool countCollection,514GCCause::Cause cause,515bool allMemoryPoolsAffected) {516517GCMemoryManager* mgr;518if (fullGC) {519mgr = (GCMemoryManager*) _major_gc_manager;520} else {521mgr = (GCMemoryManager*) _minor_gc_manager;522}523assert(mgr->is_gc_memory_manager(), "Sanity check");524525// register the GC end statistics and memory usage526mgr->gc_end(recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime,527countCollection, cause, allMemoryPoolsAffected);528}529530void MemoryService::oops_do(OopClosure* f) {531int i;532533for (i = 0; i < _pools_list->length(); i++) {534MemoryPool* pool = _pools_list->at(i);535pool->oops_do(f);536}537for (i = 0; i < _managers_list->length(); i++) {538MemoryManager* mgr = _managers_list->at(i);539mgr->oops_do(f);540}541}542543bool MemoryService::set_verbose(bool verbose) {544MutexLocker m(Management_lock);545// verbose will be set to the previous value546bool succeed = CommandLineFlags::boolAtPut((char*)"PrintGC", &verbose, Flag::MANAGEMENT);547assert(succeed, "Setting PrintGC flag fails");548ClassLoadingService::reset_trace_class_unloading();549550return verbose;551}552553Handle MemoryService::create_MemoryUsage_obj(MemoryUsage usage, TRAPS) {554Klass* k = Management::java_lang_management_MemoryUsage_klass(CHECK_NH);555instanceKlassHandle ik(THREAD, k);556557instanceHandle obj = ik->allocate_instance_handle(CHECK_NH);558559JavaValue result(T_VOID);560JavaCallArguments args(10);561args.push_oop(obj); // receiver562args.push_long(usage.init_size_as_jlong()); // Argument 1563args.push_long(usage.used_as_jlong()); // Argument 2564args.push_long(usage.committed_as_jlong()); // Argument 3565args.push_long(usage.max_size_as_jlong()); // Argument 4566567JavaCalls::call_special(&result,568ik,569vmSymbols::object_initializer_name(),570vmSymbols::long_long_long_long_void_signature(),571&args,572CHECK_NH);573return obj;574}575//576// GC manager type depends on the type of Generation. Depending on the space577// availablity and vm options the gc uses major gc manager or minor gc578// manager or both. The type of gc manager depends on the generation kind.579// For DefNew, ParNew and ASParNew generation doing scavenge gc uses minor580// gc manager (so _fullGC is set to false ) and for other generation kinds581// doing mark-sweep-compact uses major gc manager (so _fullGC is set582// to true).583TraceMemoryManagerStats::TraceMemoryManagerStats(Generation::Name kind, GCCause::Cause cause) {584switch (kind) {585case Generation::DefNew:586#if INCLUDE_ALL_GCS587case Generation::ParNew:588case Generation::ASParNew:589#endif // INCLUDE_ALL_GCS590_fullGC=false;591break;592case Generation::MarkSweepCompact:593#if INCLUDE_ALL_GCS594case Generation::ConcurrentMarkSweep:595case Generation::ASConcurrentMarkSweep:596#endif // INCLUDE_ALL_GCS597_fullGC=true;598break;599default:600assert(false, "Unrecognized gc generation kind.");601}602// this has to be called in a stop the world pause and represent603// an entire gc pause, start to finish:604initialize(_fullGC, cause, true, true, true, true, true, true, true, true);605}606TraceMemoryManagerStats::TraceMemoryManagerStats(bool fullGC,607GCCause::Cause cause,608bool allMemoryPoolsAffected,609bool recordGCBeginTime,610bool recordPreGCUsage,611bool recordPeakUsage,612bool recordPostGCUsage,613bool recordAccumulatedGCTime,614bool recordGCEndTime,615bool countCollection) {616initialize(fullGC, cause, allMemoryPoolsAffected,617recordGCBeginTime, recordPreGCUsage, recordPeakUsage,618recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime,619countCollection);620}621622// for a subclass to create then initialize an instance before invoking623// the MemoryService624void TraceMemoryManagerStats::initialize(bool fullGC,625GCCause::Cause cause,626bool allMemoryPoolsAffected,627bool recordGCBeginTime,628bool recordPreGCUsage,629bool recordPeakUsage,630bool recordPostGCUsage,631bool recordAccumulatedGCTime,632bool recordGCEndTime,633bool countCollection) {634_fullGC = fullGC;635_allMemoryPoolsAffected = allMemoryPoolsAffected;636_recordGCBeginTime = recordGCBeginTime;637_recordPreGCUsage = recordPreGCUsage;638_recordPeakUsage = recordPeakUsage;639_recordPostGCUsage = recordPostGCUsage;640_recordAccumulatedGCTime = recordAccumulatedGCTime;641_recordGCEndTime = recordGCEndTime;642_countCollection = countCollection;643_cause = cause;644645MemoryService::gc_begin(_fullGC, _recordGCBeginTime, _recordAccumulatedGCTime,646_recordPreGCUsage, _recordPeakUsage);647}648649TraceMemoryManagerStats::~TraceMemoryManagerStats() {650MemoryService::gc_end(_fullGC, _recordPostGCUsage, _recordAccumulatedGCTime,651_recordGCEndTime, _countCollection, _cause, _allMemoryPoolsAffected);652}653654655