2
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.
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
25
#include "precompiled.hpp"
26
#include "classfile/javaClasses.hpp"
27
#include "classfile/vmSymbols.hpp"
28
#include "memory/allocation.inline.hpp"
29
#include "memory/universe.hpp"
30
#include "oops/oop.inline.hpp"
31
#include "oops/oopHandle.inline.hpp"
32
#include "runtime/atomic.hpp"
33
#include "runtime/handles.inline.hpp"
34
#include "runtime/javaCalls.hpp"
35
#include "runtime/mutexLocker.hpp"
36
#include "services/lowMemoryDetector.hpp"
37
#include "services/management.hpp"
38
#include "services/memoryManager.hpp"
39
#include "services/memoryPool.hpp"
40
#include "services/memoryService.hpp"
41
#include "services/gcNotifier.hpp"
42
#include "utilities/dtrace.hpp"
44
MemoryManager::MemoryManager(const char* name)
49
_memory_mgr_obj_initialized(false)
52
int MemoryManager::add_pool(MemoryPool* pool) {
53
int index = _num_pools;
54
assert(index < MemoryManager::max_num_pools, "_num_pools exceeds the max");
55
if (index < MemoryManager::max_num_pools) {
59
pool->add_manager(this);
63
bool MemoryManager::is_manager(instanceHandle mh) const {
64
if (Atomic::load_acquire(&_memory_mgr_obj_initialized)) {
65
return mh() == _memory_mgr_obj.resolve();
71
MemoryManager* MemoryManager::get_code_cache_memory_manager() {
72
return new MemoryManager("CodeCacheManager");
75
MemoryManager* MemoryManager::get_metaspace_memory_manager() {
76
return new MemoryManager("Metaspace Manager");
79
instanceOop MemoryManager::get_memory_manager_instance(TRAPS) {
80
// Lazily create the manager object.
81
// Must do an acquire so as to force ordering of subsequent
82
// loads from anything _memory_mgr_obj points to or implies.
83
if (!Atomic::load_acquire(&_memory_mgr_obj_initialized)) {
84
// It's ok for more than one thread to execute the code up to the locked region.
85
// Extra manager instances will just be gc'ed.
86
Klass* k = Management::sun_management_ManagementFactoryHelper_klass(CHECK_NULL);
88
Handle mgr_name = java_lang_String::create_from_str(name(), CHECK_NULL);
90
JavaValue result(T_OBJECT);
91
JavaCallArguments args;
92
args.push_oop(mgr_name); // Argument 1
94
Symbol* method_name = nullptr;
95
Symbol* signature = nullptr;
96
if (is_gc_memory_manager()) {
97
Klass* extKlass = Management::com_sun_management_internal_GarbageCollectorExtImpl_klass(CHECK_NULL);
98
// com.sun.management.GarbageCollectorMXBean is in jdk.management module which may not be present.
99
if (extKlass != nullptr) {
103
method_name = vmSymbols::createGarbageCollector_name();
105
signature = vmSymbols::createGarbageCollector_signature();
106
args.push_oop(Handle()); // Argument 2 (for future extension)
108
method_name = vmSymbols::createMemoryManager_name();
109
signature = vmSymbols::createMemoryManager_signature();
113
fatal("Should have the ManagementFactoryHelper or GarbageCollectorExtImpl class");
114
return nullptr; // silence the compiler
117
InstanceKlass* ik = InstanceKlass::cast(k);
119
JavaCalls::call_static(&result,
126
// Verify we didn't get a null manager. If that could happen then we'd
127
// need to return immediately rather than continuing on and recording the
128
// manager has been created.
129
oop m = result.get_oop();
130
guarantee(m != nullptr, "Manager creation returned null");
131
instanceHandle mgr(THREAD, (instanceOop)m);
133
// Allocate global handle outside lock, to avoid any lock nesting issues
134
// with the Management_lock.
135
OopHandle mgr_handle(Universe::vm_global(), mgr());
137
// Get lock since another thread may have created and installed the instance.
138
MutexLocker ml(THREAD, Management_lock);
140
if (Atomic::load(&_memory_mgr_obj_initialized)) {
141
// Some other thread won the race. Release the handle we allocated and
142
// use the other one. Relaxed load is sufficient because flag update is
144
mgr_handle.release(Universe::vm_global());
146
// Record the object we created via call_special.
147
assert(_memory_mgr_obj.is_empty(), "already set manager obj");
148
_memory_mgr_obj = mgr_handle;
149
// Record manager has been created. Release matching unlocked acquire,
150
// to safely publish the manager object.
151
Atomic::release_store(&_memory_mgr_obj_initialized, true);
155
return (instanceOop)_memory_mgr_obj.resolve();
158
GCStatInfo::GCStatInfo(int num_pools) {
159
// initialize the arrays for memory usage
160
_before_gc_usage_array = NEW_C_HEAP_ARRAY(MemoryUsage, num_pools, mtInternal);
161
_after_gc_usage_array = NEW_C_HEAP_ARRAY(MemoryUsage, num_pools, mtInternal);
162
_usage_array_size = num_pools;
166
GCStatInfo::~GCStatInfo() {
167
FREE_C_HEAP_ARRAY(MemoryUsage*, _before_gc_usage_array);
168
FREE_C_HEAP_ARRAY(MemoryUsage*, _after_gc_usage_array);
171
void GCStatInfo::set_gc_usage(int pool_index, MemoryUsage usage, bool before_gc) {
172
MemoryUsage* gc_usage_array;
174
gc_usage_array = _before_gc_usage_array;
176
gc_usage_array = _after_gc_usage_array;
178
gc_usage_array[pool_index] = usage;
181
void GCStatInfo::clear() {
185
for (int i = 0; i < _usage_array_size; i++) ::new (&_before_gc_usage_array[i]) MemoryUsage();
186
for (int i = 0; i < _usage_array_size; i++) ::new (&_after_gc_usage_array[i]) MemoryUsage();
190
GCMemoryManager::GCMemoryManager(const char* name) :
191
MemoryManager(name) {
192
_num_collections = 0;
193
_last_gc_stat = nullptr;
194
_last_gc_lock = new Mutex(Mutex::nosafepoint, "GCMemoryManager_lock");
195
_current_gc_stat = nullptr;
197
_notification_enabled = false;
200
GCMemoryManager::~GCMemoryManager() {
201
delete _last_gc_stat;
202
delete _last_gc_lock;
203
delete _current_gc_stat;
206
void GCMemoryManager::add_pool(MemoryPool* pool) {
207
add_pool(pool, true);
210
void GCMemoryManager::add_pool(MemoryPool* pool, bool always_affected_by_gc) {
211
int index = MemoryManager::add_pool(pool);
212
_pool_always_affected_by_gc[index] = always_affected_by_gc;
215
void GCMemoryManager::initialize_gc_stat_info() {
216
assert(MemoryService::num_memory_pools() > 0, "should have one or more memory pools");
217
_last_gc_stat = new GCStatInfo(MemoryService::num_memory_pools());
218
_current_gc_stat = new GCStatInfo(MemoryService::num_memory_pools());
219
// tracking concurrent collections we need two objects: one to update, and one to
220
// hold the publicly available "last (completed) gc" information.
223
void GCMemoryManager::gc_begin(bool recordGCBeginTime, bool recordPreGCUsage,
224
bool recordAccumulatedGCTime) {
225
assert(_last_gc_stat != nullptr && _current_gc_stat != nullptr, "Just checking");
226
if (recordAccumulatedGCTime) {
227
_accumulated_timer.start();
229
// _num_collections now increases in gc_end, to count completed collections
230
if (recordGCBeginTime) {
231
_current_gc_stat->set_index(_num_collections+1);
232
_current_gc_stat->set_start_time(Management::timestamp());
235
if (recordPreGCUsage) {
236
// Keep memory usage of all memory pools
237
for (int i = 0; i < MemoryService::num_memory_pools(); i++) {
238
MemoryPool* pool = MemoryService::get_memory_pool(i);
239
MemoryUsage usage = pool->get_memory_usage();
240
_current_gc_stat->set_before_gc_usage(i, usage);
241
HOTSPOT_MEM_POOL_GC_BEGIN(
242
(char *) name(), strlen(name()),
243
(char *) pool->name(), strlen(pool->name()),
244
usage.init_size(), usage.used(),
245
usage.committed(), usage.max_size());
250
// A collector MUST, even if it does not complete for some reason,
251
// make a TraceMemoryManagerStats object where countCollection is true,
252
// to ensure the current gc stat is placed in _last_gc_stat.
253
void GCMemoryManager::gc_end(bool recordPostGCUsage,
254
bool recordAccumulatedGCTime,
255
bool recordGCEndTime,
256
bool countCollection,
257
GCCause::Cause cause,
258
bool allMemoryPoolsAffected,
259
const char* message) {
260
if (recordAccumulatedGCTime) {
261
_accumulated_timer.stop();
263
if (recordGCEndTime) {
264
_current_gc_stat->set_end_time(Management::timestamp());
267
if (recordPostGCUsage) {
269
// keep the last gc statistics for all memory pools
270
for (i = 0; i < MemoryService::num_memory_pools(); i++) {
271
MemoryPool* pool = MemoryService::get_memory_pool(i);
272
MemoryUsage usage = pool->get_memory_usage();
274
HOTSPOT_MEM_POOL_GC_END(
275
(char *) name(), strlen(name()),
276
(char *) pool->name(), strlen(pool->name()),
277
usage.init_size(), usage.used(),
278
usage.committed(), usage.max_size());
280
_current_gc_stat->set_after_gc_usage(i, usage);
283
// Set last collection usage of the memory pools managed by this collector
284
for (i = 0; i < num_memory_pools(); i++) {
285
MemoryPool* pool = get_memory_pool(i);
286
MemoryUsage usage = pool->get_memory_usage();
288
if (allMemoryPoolsAffected || pool_always_affected_by_gc(i)) {
289
// Compare with GC usage threshold
290
pool->set_last_collection_usage(usage);
291
LowMemoryDetector::detect_after_gc_memory(pool);
296
if (countCollection) {
298
// alternately update two objects making one public when complete
300
MutexLocker ml(_last_gc_lock, Mutex::_no_safepoint_check_flag);
301
GCStatInfo *tmp = _last_gc_stat;
302
_last_gc_stat = _current_gc_stat;
303
_current_gc_stat = tmp;
304
// reset the current stat for diagnosability purposes
305
_current_gc_stat->clear();
308
if (is_notification_enabled()) {
309
GCNotifier::pushNotification(this, message, GCCause::to_string(cause));
314
size_t GCMemoryManager::get_last_gc_stat(GCStatInfo* dest) {
315
MutexLocker ml(_last_gc_lock, Mutex::_no_safepoint_check_flag);
316
if (_last_gc_stat->gc_index() != 0) {
317
dest->set_index(_last_gc_stat->gc_index());
318
dest->set_start_time(_last_gc_stat->start_time());
319
dest->set_end_time(_last_gc_stat->end_time());
320
assert(dest->usage_array_size() == _last_gc_stat->usage_array_size(),
321
"Must have same array size");
322
size_t len = dest->usage_array_size() * sizeof(MemoryUsage);
323
memcpy(dest->before_gc_usage_array(), _last_gc_stat->before_gc_usage_array(), len);
324
memcpy(dest->after_gc_usage_array(), _last_gc_stat->after_gc_usage_array(), len);
326
return _last_gc_stat->gc_index();