/* * Copyright (c) 2003, 2022, 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. *
*/
instanceOop MemoryManager::get_memory_manager_instance(TRAPS) { // Must do an acquire so as to force ordering of subsequent // loads from anything _memory_mgr_obj points to or implies.
oop mgr_obj = Atomic::load_acquire(&_memory_mgr_obj).resolve(); if (mgr_obj == NULL) { // It's ok for more than one thread to execute the code up to the locked region. // Extra manager instances will just be gc'ed.
Klass* k = Management::sun_management_ManagementFactoryHelper_klass(CHECK_NULL);
Symbol* method_name = NULL;
Symbol* signature = NULL; if (is_gc_memory_manager()) {
Klass* extKlass = Management::com_sun_management_internal_GarbageCollectorExtImpl_klass(CHECK_NULL); // com.sun.management.GarbageCollectorMXBean is in jdk.management module which may not be present. if (extKlass != NULL) {
k = extKlass;
}
instanceOop m = (instanceOop) result.get_oop();
instanceHandle mgr(THREAD, m);
{ // Get lock before setting _memory_mgr_obj // since another thread may have created the instance
MutexLocker ml(THREAD, Management_lock);
// Check if another thread has created the management object. We reload // _memory_mgr_obj here because some other thread may have initialized // it while we were executing the code before the lock.
mgr_obj = Atomic::load(&_memory_mgr_obj).resolve(); if (mgr_obj != NULL) { return (instanceOop)mgr_obj;
}
// Get the address of the object we created via call_special.
mgr_obj = mgr();
// Use store barrier to make sure the memory accesses associated // with creating the management object are visible before publishing // its address. The unlock will publish the store to _memory_mgr_obj // because it does a release first.
Atomic::release_store(&_memory_mgr_obj, OopHandle(Universe::vm_global(), mgr_obj));
}
}
void GCMemoryManager::add_pool(MemoryPool* pool, bool always_affected_by_gc) { int index = MemoryManager::add_pool(pool);
_pool_always_affected_by_gc[index] = always_affected_by_gc;
}
void GCMemoryManager::initialize_gc_stat_info() {
assert(MemoryService::num_memory_pools() > 0, "should have one or more memory pools");
_last_gc_stat = new GCStatInfo(MemoryService::num_memory_pools());
_current_gc_stat = new GCStatInfo(MemoryService::num_memory_pools()); // tracking concurrent collections we need two objects: one to update, and one to // hold the publicly available "last (completed) gc" information.
}
void GCMemoryManager::gc_begin(bool recordGCBeginTime, bool recordPreGCUsage, bool recordAccumulatedGCTime) {
assert(_last_gc_stat != NULL && _current_gc_stat != NULL, "Just checking"); if (recordAccumulatedGCTime) {
_accumulated_timer.start();
} // _num_collections now increases in gc_end, to count completed collections if (recordGCBeginTime) {
_current_gc_stat->set_index(_num_collections+1);
_current_gc_stat->set_start_time(Management::timestamp());
}
if (recordPreGCUsage) { // Keep memory usage of all memory pools for (int i = 0; i < MemoryService::num_memory_pools(); i++) {
MemoryPool* pool = MemoryService::get_memory_pool(i);
MemoryUsage usage = pool->get_memory_usage();
_current_gc_stat->set_before_gc_usage(i, usage);
HOTSPOT_MEM_POOL_GC_BEGIN(
(char *) name(), strlen(name()),
(char *) pool->name(), strlen(pool->name()),
usage.init_size(), usage.used(),
usage.committed(), usage.max_size());
}
}
}
// A collector MUST, even if it does not complete for some reason, // make a TraceMemoryManagerStats object where countCollection is true, // to ensure the current gc stat is placed in _last_gc_stat. void GCMemoryManager::gc_end(bool recordPostGCUsage, bool recordAccumulatedGCTime, bool recordGCEndTime, bool countCollection,
GCCause::Cause cause, bool allMemoryPoolsAffected) { if (recordAccumulatedGCTime) {
_accumulated_timer.stop();
} if (recordGCEndTime) {
_current_gc_stat->set_end_time(Management::timestamp());
}
if (recordPostGCUsage) { int i; // keep the last gc statistics for all memory pools for (i = 0; i < MemoryService::num_memory_pools(); i++) {
MemoryPool* pool = MemoryService::get_memory_pool(i);
MemoryUsage usage = pool->get_memory_usage();
// Set last collection usage of the memory pools managed by this collector for (i = 0; i < num_memory_pools(); i++) {
MemoryPool* pool = get_memory_pool(i);
MemoryUsage usage = pool->get_memory_usage();
if (allMemoryPoolsAffected || pool_always_affected_by_gc(i)) { // Compare with GC usage threshold
pool->set_last_collection_usage(usage);
LowMemoryDetector::detect_after_gc_memory(pool);
}
}
}
if (countCollection) {
_num_collections++; // alternately update two objects making one public when complete
{
MutexLocker ml(_last_gc_lock, Mutex::_no_safepoint_check_flag);
GCStatInfo *tmp = _last_gc_stat;
_last_gc_stat = _current_gc_stat;
_current_gc_stat = tmp; // reset the current stat for diagnosability purposes
_current_gc_stat->clear();
}
if (is_notification_enabled()) {
GCNotifier::pushNotification(this, _gc_end_message, GCCause::to_string(cause));
}
}
}
size_t GCMemoryManager::get_last_gc_stat(GCStatInfo* dest) {
MutexLocker ml(_last_gc_lock, Mutex::_no_safepoint_check_flag); if (_last_gc_stat->gc_index() != 0) {
dest->set_index(_last_gc_stat->gc_index());
dest->set_start_time(_last_gc_stat->start_time());
dest->set_end_time(_last_gc_stat->end_time());
assert(dest->usage_array_size() == _last_gc_stat->usage_array_size(), "Must have same array size");
size_t len = dest->usage_array_size() * sizeof(MemoryUsage);
memcpy(dest->before_gc_usage_array(), _last_gc_stat->before_gc_usage_array(), len);
memcpy(dest->after_gc_usage_array(), _last_gc_stat->after_gc_usage_array(), len);
} return _last_gc_stat->gc_index();
}
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.