1 | /* |
2 | * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. |
8 | * |
9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | * version 2 for more details (a copy is included in the LICENSE file that |
13 | * accompanied this code). |
14 | * |
15 | * You should have received a copy of the GNU General Public License version |
16 | * 2 along with this work; if not, write to the Free Software Foundation, |
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | |
25 | #ifndef SHARE_SERVICES_MEMORYMANAGER_HPP |
26 | #define SHARE_SERVICES_MEMORYMANAGER_HPP |
27 | |
28 | #include "gc/shared/gcCause.hpp" |
29 | #include "memory/allocation.hpp" |
30 | #include "oops/oop.hpp" |
31 | #include "oops/oopsHierarchy.hpp" |
32 | #include "runtime/handles.hpp" |
33 | #include "runtime/timer.hpp" |
34 | #include "services/memoryUsage.hpp" |
35 | |
36 | // A memory manager is responsible for managing one or more memory pools. |
37 | // The garbage collector is one type of memory managers responsible |
38 | // for reclaiming memory occupied by unreachable objects. A Java virtual |
39 | // machine may have one or more memory managers. It may |
40 | // add or remove memory managers during execution. |
41 | // A memory pool can be managed by more than one memory managers. |
42 | |
43 | class MemoryPool; |
44 | class GCMemoryManager; |
45 | class OopClosure; |
46 | |
47 | class MemoryManager : public CHeapObj<mtInternal> { |
48 | protected: |
49 | enum { |
50 | max_num_pools = 10 |
51 | }; |
52 | |
53 | private: |
54 | MemoryPool* _pools[max_num_pools]; |
55 | int _num_pools; |
56 | |
57 | const char* _name; |
58 | |
59 | protected: |
60 | volatile instanceOop _memory_mgr_obj; |
61 | |
62 | public: |
63 | MemoryManager(const char* name); |
64 | |
65 | int num_memory_pools() const { return _num_pools; } |
66 | MemoryPool* get_memory_pool(int index) { |
67 | assert(index >= 0 && index < _num_pools, "Invalid index" ); |
68 | return _pools[index]; |
69 | } |
70 | |
71 | int add_pool(MemoryPool* pool); |
72 | |
73 | bool is_manager(instanceHandle mh) { return oopDesc::equals(mh(), _memory_mgr_obj); } |
74 | |
75 | virtual instanceOop get_memory_manager_instance(TRAPS); |
76 | virtual bool is_gc_memory_manager() { return false; } |
77 | |
78 | const char* name() const { return _name; } |
79 | |
80 | // GC support |
81 | void oops_do(OopClosure* f); |
82 | |
83 | // Static factory methods to get a memory manager of a specific type |
84 | static MemoryManager* get_code_cache_memory_manager(); |
85 | static MemoryManager* get_metaspace_memory_manager(); |
86 | }; |
87 | |
88 | class GCStatInfo : public ResourceObj { |
89 | private: |
90 | size_t _index; |
91 | jlong _start_time; |
92 | jlong _end_time; |
93 | |
94 | // We keep memory usage of all memory pools |
95 | MemoryUsage* _before_gc_usage_array; |
96 | MemoryUsage* _after_gc_usage_array; |
97 | int _usage_array_size; |
98 | |
99 | void set_gc_usage(int pool_index, MemoryUsage, bool before_gc); |
100 | |
101 | public: |
102 | GCStatInfo(int num_pools); |
103 | ~GCStatInfo(); |
104 | |
105 | size_t gc_index() { return _index; } |
106 | jlong start_time() { return _start_time; } |
107 | jlong end_time() { return _end_time; } |
108 | int usage_array_size() { return _usage_array_size; } |
109 | MemoryUsage before_gc_usage_for_pool(int pool_index) { |
110 | assert(pool_index >= 0 && pool_index < _usage_array_size, "Range checking" ); |
111 | return _before_gc_usage_array[pool_index]; |
112 | } |
113 | MemoryUsage after_gc_usage_for_pool(int pool_index) { |
114 | assert(pool_index >= 0 && pool_index < _usage_array_size, "Range checking" ); |
115 | return _after_gc_usage_array[pool_index]; |
116 | } |
117 | |
118 | MemoryUsage* before_gc_usage_array() { return _before_gc_usage_array; } |
119 | MemoryUsage* after_gc_usage_array() { return _after_gc_usage_array; } |
120 | |
121 | void set_index(size_t index) { _index = index; } |
122 | void set_start_time(jlong time) { _start_time = time; } |
123 | void set_end_time(jlong time) { _end_time = time; } |
124 | void set_before_gc_usage(int pool_index, MemoryUsage usage) { |
125 | assert(pool_index >= 0 && pool_index < _usage_array_size, "Range checking" ); |
126 | set_gc_usage(pool_index, usage, true /* before gc */); |
127 | } |
128 | void set_after_gc_usage(int pool_index, MemoryUsage usage) { |
129 | assert(pool_index >= 0 && pool_index < _usage_array_size, "Range checking" ); |
130 | set_gc_usage(pool_index, usage, false /* after gc */); |
131 | } |
132 | |
133 | void clear(); |
134 | }; |
135 | |
136 | class GCMemoryManager : public MemoryManager { |
137 | private: |
138 | // TODO: We should unify the GCCounter and GCMemoryManager statistic |
139 | size_t _num_collections; |
140 | elapsedTimer _accumulated_timer; |
141 | GCStatInfo* _last_gc_stat; |
142 | Mutex* _last_gc_lock; |
143 | GCStatInfo* _current_gc_stat; |
144 | int _num_gc_threads; |
145 | volatile bool _notification_enabled; |
146 | const char* _gc_end_message; |
147 | bool _pool_always_affected_by_gc[MemoryManager::max_num_pools]; |
148 | |
149 | public: |
150 | GCMemoryManager(const char* name, const char* gc_end_message); |
151 | ~GCMemoryManager(); |
152 | |
153 | void add_pool(MemoryPool* pool); |
154 | void add_pool(MemoryPool* pool, bool always_affected_by_gc); |
155 | |
156 | bool pool_always_affected_by_gc(int index) { |
157 | assert(index >= 0 && index < num_memory_pools(), "Invalid index" ); |
158 | return _pool_always_affected_by_gc[index]; |
159 | } |
160 | |
161 | void initialize_gc_stat_info(); |
162 | |
163 | bool is_gc_memory_manager() { return true; } |
164 | jlong gc_time_ms() { return _accumulated_timer.milliseconds(); } |
165 | size_t gc_count() { return _num_collections; } |
166 | int num_gc_threads() { return _num_gc_threads; } |
167 | void set_num_gc_threads(int count) { _num_gc_threads = count; } |
168 | |
169 | void gc_begin(bool recordGCBeginTime, bool recordPreGCUsage, |
170 | bool recordAccumulatedGCTime); |
171 | void gc_end(bool recordPostGCUsage, bool recordAccumulatedGCTime, |
172 | bool recordGCEndTime, bool countCollection, GCCause::Cause cause, |
173 | bool allMemoryPoolsAffected); |
174 | |
175 | void reset_gc_stat() { _num_collections = 0; _accumulated_timer.reset(); } |
176 | |
177 | // Copy out _last_gc_stat to the given destination, returning |
178 | // the collection count. Zero signifies no gc has taken place. |
179 | size_t get_last_gc_stat(GCStatInfo* dest); |
180 | |
181 | void set_notification_enabled(bool enabled) { _notification_enabled = enabled; } |
182 | bool is_notification_enabled() { return _notification_enabled; } |
183 | }; |
184 | |
185 | #endif // SHARE_SERVICES_MEMORYMANAGER_HPP |
186 | |