hotspot/src/share/vm/services/memoryManager.cpp
// 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) {
{- -------------------------------------------
(1) (引数の recordAccumulatedGCTime が指定されていれば) GC 終了時の時刻を記録しておく.
(See: sun.management.GarbageCollectorImpl.getCollectionTime())
---------------------------------------- -}
if (recordAccumulatedGCTime) {
_accumulated_timer.stop();
}
{- -------------------------------------------
(1) (引数の recordGCBeginTime が指定されていれば) GC 終了時の時刻を記録しておく.
(See: GCStatInfo)
---------------------------------------- -}
if (recordGCEndTime) {
_current_gc_stat->set_end_time(Management::timestamp());
}
{- -------------------------------------------
(1) (引数の recordPostGCUsage が指定されていれば)
全ての MemoryPool に対して, GCStatInfo::set_after_gc_usage() で
GC 終了時の使用量を記録しておく.
なお, (DTrace のフック点) でもある.
また, (JMM のフック点) でもある.
* 全ての MemoryPool に対して, LowMemoryDetector::detect_after_gc_memory() が呼び出される.
(See: LowMemoryDetector)
* もし GCNotifier の通知を行う必要があれば (= GCNotifier::is_notification_enabled() が true ならば)
GCNotifier::pushNotification() が呼び出される.
(See: GCNotifier)
---------------------------------------- -}
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();
HS_DTRACE_PROBE8(hotspot, mem__pool__gc__end,
name(), strlen(name()),
pool->name(), strlen(pool->name()),
usage.init_size(), usage.used(),
usage.committed(), usage.max_size());
_current_gc_stat->set_after_gc_usage(i, 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();
// Compare with GC usage threshold
pool->set_last_collection_usage(usage);
LowMemoryDetector::detect_after_gc_memory(pool);
}
if(is_notification_enabled()) {
bool isMajorGC = this == MemoryService::get_major_gc_manager();
GCNotifier::pushNotification(this, isMajorGC ? "end of major GC" : "end of minor GC",
GCCause::to_string(cause));
}
}
{- -------------------------------------------
(1) (引数の countCollection が指定されていれば)
GC 回数 (_num_collections フィールド) の値をインクリメントし,
_last_gc_stat フィールドと _current_gc_stat フィールドの値を入れ替えておく.
(See: GCMemoryManager::get_last_gc_stat())
---------------------------------------- -}
if (countCollection) {
_num_collections++;
// alternately update two objects making one public when complete
{
MutexLockerEx 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();
}
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.