duke@435: /* mikael@6198: * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #ifndef SHARE_VM_SERVICES_MEMORYMANAGER_HPP stefank@2314: #define SHARE_VM_SERVICES_MEMORYMANAGER_HPP stefank@2314: stefank@2314: #include "memory/allocation.hpp" stefank@2314: #include "runtime/timer.hpp" stefank@2314: #include "services/memoryUsage.hpp" stefank@2314: duke@435: // A memory manager is responsible for managing one or more memory pools. duke@435: // The garbage collector is one type of memory managers responsible duke@435: // for reclaiming memory occupied by unreachable objects. A Java virtual duke@435: // machine may have one or more memory managers. It may duke@435: // add or remove memory managers during execution. duke@435: // A memory pool can be managed by more than one memory managers. duke@435: duke@435: class MemoryPool; duke@435: class GCMemoryManager; duke@435: class OopClosure; duke@435: zgu@3900: class MemoryManager : public CHeapObj { duke@435: private: duke@435: enum { duke@435: max_num_pools = 10 duke@435: }; duke@435: duke@435: MemoryPool* _pools[max_num_pools]; duke@435: int _num_pools; duke@435: duke@435: protected: duke@435: volatile instanceOop _memory_mgr_obj; duke@435: duke@435: public: duke@435: enum Name { duke@435: Abstract, duke@435: CodeCache, ehelin@5312: Metaspace, duke@435: Copy, duke@435: MarkSweepCompact, duke@435: ParNew, duke@435: ConcurrentMarkSweep, duke@435: PSScavenge, tonyp@1524: PSMarkSweep, tonyp@1524: G1YoungGen, tonyp@1524: G1OldGen duke@435: }; duke@435: duke@435: MemoryManager(); duke@435: duke@435: int num_memory_pools() const { return _num_pools; } duke@435: MemoryPool* get_memory_pool(int index) { duke@435: assert(index >= 0 && index < _num_pools, "Invalid index"); duke@435: return _pools[index]; duke@435: } duke@435: duke@435: void add_pool(MemoryPool* pool); duke@435: duke@435: bool is_manager(instanceHandle mh) { return mh() == _memory_mgr_obj; } duke@435: duke@435: virtual instanceOop get_memory_manager_instance(TRAPS); duke@435: virtual MemoryManager::Name kind() { return MemoryManager::Abstract; } duke@435: virtual bool is_gc_memory_manager() { return false; } duke@435: virtual const char* name() = 0; duke@435: duke@435: // GC support duke@435: void oops_do(OopClosure* f); duke@435: duke@435: // Static factory methods to get a memory manager of a specific type duke@435: static MemoryManager* get_code_cache_memory_manager(); ehelin@5312: static MemoryManager* get_metaspace_memory_manager(); duke@435: static GCMemoryManager* get_copy_memory_manager(); duke@435: static GCMemoryManager* get_msc_memory_manager(); duke@435: static GCMemoryManager* get_parnew_memory_manager(); duke@435: static GCMemoryManager* get_cms_memory_manager(); duke@435: static GCMemoryManager* get_psScavenge_memory_manager(); duke@435: static GCMemoryManager* get_psMarkSweep_memory_manager(); tonyp@1524: static GCMemoryManager* get_g1YoungGen_memory_manager(); tonyp@1524: static GCMemoryManager* get_g1OldGen_memory_manager(); duke@435: duke@435: }; duke@435: duke@435: class CodeCacheMemoryManager : public MemoryManager { duke@435: private: duke@435: public: duke@435: CodeCacheMemoryManager() : MemoryManager() {} duke@435: duke@435: MemoryManager::Name kind() { return MemoryManager::CodeCache; } duke@435: const char* name() { return "CodeCacheManager"; } duke@435: }; duke@435: ehelin@5312: class MetaspaceMemoryManager : public MemoryManager { ehelin@5312: public: ehelin@5312: MetaspaceMemoryManager() : MemoryManager() {} ehelin@5312: ehelin@5312: MemoryManager::Name kind() { return MemoryManager::Metaspace; } ehelin@5312: const char *name() { return "Metaspace Manager"; } ehelin@5312: }; ehelin@5312: dsamersoff@3471: class GCStatInfo : public ResourceObj { duke@435: private: duke@435: size_t _index; duke@435: jlong _start_time; duke@435: jlong _end_time; duke@435: duke@435: // We keep memory usage of all memory pools duke@435: MemoryUsage* _before_gc_usage_array; duke@435: MemoryUsage* _after_gc_usage_array; duke@435: int _usage_array_size; duke@435: duke@435: void set_gc_usage(int pool_index, MemoryUsage, bool before_gc); duke@435: duke@435: public: duke@435: GCStatInfo(int num_pools); duke@435: ~GCStatInfo(); duke@435: duke@435: size_t gc_index() { return _index; } duke@435: jlong start_time() { return _start_time; } duke@435: jlong end_time() { return _end_time; } duke@435: int usage_array_size() { return _usage_array_size; } duke@435: MemoryUsage before_gc_usage_for_pool(int pool_index) { duke@435: assert(pool_index >= 0 && pool_index < _usage_array_size, "Range checking"); duke@435: return _before_gc_usage_array[pool_index]; duke@435: } duke@435: MemoryUsage after_gc_usage_for_pool(int pool_index) { duke@435: assert(pool_index >= 0 && pool_index < _usage_array_size, "Range checking"); duke@435: return _after_gc_usage_array[pool_index]; duke@435: } duke@435: kevinw@2058: MemoryUsage* before_gc_usage_array() { return _before_gc_usage_array; } kevinw@2058: MemoryUsage* after_gc_usage_array() { return _after_gc_usage_array; } kevinw@2058: duke@435: void set_index(size_t index) { _index = index; } duke@435: void set_start_time(jlong time) { _start_time = time; } duke@435: void set_end_time(jlong time) { _end_time = time; } duke@435: void set_before_gc_usage(int pool_index, MemoryUsage usage) { duke@435: assert(pool_index >= 0 && pool_index < _usage_array_size, "Range checking"); duke@435: set_gc_usage(pool_index, usage, true /* before gc */); duke@435: } duke@435: void set_after_gc_usage(int pool_index, MemoryUsage usage) { duke@435: assert(pool_index >= 0 && pool_index < _usage_array_size, "Range checking"); duke@435: set_gc_usage(pool_index, usage, false /* after gc */); duke@435: } duke@435: kevinw@2058: void clear(); duke@435: }; duke@435: duke@435: class GCMemoryManager : public MemoryManager { duke@435: private: duke@435: // TODO: We should unify the GCCounter and GCMemoryManager statistic duke@435: size_t _num_collections; duke@435: elapsedTimer _accumulated_timer; duke@435: elapsedTimer _gc_timer; // for measuring every GC duration duke@435: GCStatInfo* _last_gc_stat; kevinw@2058: Mutex* _last_gc_lock; kevinw@2058: GCStatInfo* _current_gc_stat; duke@435: int _num_gc_threads; fparain@2888: volatile bool _notification_enabled; duke@435: public: duke@435: GCMemoryManager(); duke@435: ~GCMemoryManager(); duke@435: duke@435: void initialize_gc_stat_info(); duke@435: duke@435: bool is_gc_memory_manager() { return true; } duke@435: jlong gc_time_ms() { return _accumulated_timer.milliseconds(); } duke@435: size_t gc_count() { return _num_collections; } duke@435: int num_gc_threads() { return _num_gc_threads; } duke@435: void set_num_gc_threads(int count) { _num_gc_threads = count; } duke@435: kevinw@2058: void gc_begin(bool recordGCBeginTime, bool recordPreGCUsage, kevinw@2058: bool recordAccumulatedGCTime); kevinw@2058: void gc_end(bool recordPostGCUsage, bool recordAccumulatedGCTime, fparain@2888: bool recordGCEndTime, bool countCollection, GCCause::Cause cause); duke@435: duke@435: void reset_gc_stat() { _num_collections = 0; _accumulated_timer.reset(); } kevinw@2058: kevinw@2058: // Copy out _last_gc_stat to the given destination, returning kevinw@2058: // the collection count. Zero signifies no gc has taken place. kevinw@2058: size_t get_last_gc_stat(GCStatInfo* dest); duke@435: fparain@2888: void set_notification_enabled(bool enabled) { _notification_enabled = enabled; } fparain@2888: bool is_notification_enabled() { return _notification_enabled; } duke@435: virtual MemoryManager::Name kind() = 0; duke@435: }; duke@435: duke@435: // These subclasses of GCMemoryManager are defined to include duke@435: // GC-specific information. duke@435: // TODO: Add GC-specific information duke@435: class CopyMemoryManager : public GCMemoryManager { duke@435: private: duke@435: public: duke@435: CopyMemoryManager() : GCMemoryManager() {} duke@435: duke@435: MemoryManager::Name kind() { return MemoryManager::Copy; } duke@435: const char* name() { return "Copy"; } duke@435: }; duke@435: duke@435: class MSCMemoryManager : public GCMemoryManager { duke@435: private: duke@435: public: duke@435: MSCMemoryManager() : GCMemoryManager() {} duke@435: duke@435: MemoryManager::Name kind() { return MemoryManager::MarkSweepCompact; } duke@435: const char* name() { return "MarkSweepCompact"; } duke@435: duke@435: }; duke@435: duke@435: class ParNewMemoryManager : public GCMemoryManager { duke@435: private: duke@435: public: duke@435: ParNewMemoryManager() : GCMemoryManager() {} duke@435: duke@435: MemoryManager::Name kind() { return MemoryManager::ParNew; } duke@435: const char* name() { return "ParNew"; } duke@435: duke@435: }; duke@435: duke@435: class CMSMemoryManager : public GCMemoryManager { duke@435: private: duke@435: public: duke@435: CMSMemoryManager() : GCMemoryManager() {} duke@435: duke@435: MemoryManager::Name kind() { return MemoryManager::ConcurrentMarkSweep; } duke@435: const char* name() { return "ConcurrentMarkSweep";} duke@435: duke@435: }; duke@435: duke@435: class PSScavengeMemoryManager : public GCMemoryManager { duke@435: private: duke@435: public: duke@435: PSScavengeMemoryManager() : GCMemoryManager() {} duke@435: duke@435: MemoryManager::Name kind() { return MemoryManager::PSScavenge; } duke@435: const char* name() { return "PS Scavenge"; } duke@435: duke@435: }; duke@435: duke@435: class PSMarkSweepMemoryManager : public GCMemoryManager { duke@435: private: duke@435: public: duke@435: PSMarkSweepMemoryManager() : GCMemoryManager() {} duke@435: duke@435: MemoryManager::Name kind() { return MemoryManager::PSMarkSweep; } duke@435: const char* name() { return "PS MarkSweep"; } duke@435: }; tonyp@1524: tonyp@1524: class G1YoungGenMemoryManager : public GCMemoryManager { tonyp@1524: private: tonyp@1524: public: tonyp@1524: G1YoungGenMemoryManager() : GCMemoryManager() {} tonyp@1524: tonyp@1524: MemoryManager::Name kind() { return MemoryManager::G1YoungGen; } tonyp@1524: const char* name() { return "G1 Young Generation"; } tonyp@1524: }; tonyp@1524: tonyp@1524: class G1OldGenMemoryManager : public GCMemoryManager { tonyp@1524: private: tonyp@1524: public: tonyp@1524: G1OldGenMemoryManager() : GCMemoryManager() {} tonyp@1524: tonyp@1524: MemoryManager::Name kind() { return MemoryManager::G1OldGen; } tonyp@1524: const char* name() { return "G1 Old Generation"; } tonyp@1524: }; stefank@2314: stefank@2314: #endif // SHARE_VM_SERVICES_MEMORYMANAGER_HPP