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); #ifndef USDT2 HS_DTRACE_PROBE8(hotspot, mem__pool__gc__begin, name(), strlen(name()), pool->name(), strlen(pool->name()), usage.init_size(), usage.used(), usage.committed(), usage.max_size()); #else /* USDT2 */ 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()); #endif /* USDT2 */ } } }
void GCMemoryManager::gc_end() { _accumulated_timer.stop(); _last_gc_stat->set_end_time(Management::timestamp()); 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()); _last_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); } }
// 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) { 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(); 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)); } } 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(); } } }
void GCMemoryManager::gc_begin() { assert(_last_gc_stat != NULL, "Just checking"); _accumulated_timer.start(); _num_collections++; _last_gc_stat->set_index(_num_collections); _last_gc_stat->set_start_time(Management::timestamp()); // 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(); _last_gc_stat->set_before_gc_usage(i, usage); HS_DTRACE_PROBE8(hotspot, mem__pool__gc__begin, name(), strlen(name()), pool->name(), strlen(pool->name()), usage.init_size(), usage.used(), usage.committed(), usage.max_size()); } }
static Handle createGcInfo(GCMemoryManager *gcManager, GCStatInfo *gcStatInfo,TRAPS) { // Fill the arrays of MemoryUsage objects with before and after GC // per pool memory usage Klass* mu_klass = Management::java_lang_management_MemoryUsage_klass(CHECK_NH); instanceKlassHandle mu_kh(THREAD, mu_klass); // The array allocations below should use a handle containing mu_klass // as the first allocation could trigger a GC, causing the actual // klass oop to move, and leaving mu_klass pointing to the old // location. objArrayOop bu = oopFactory::new_objArray(mu_kh(), MemoryService::num_memory_pools(), CHECK_NH); objArrayHandle usage_before_gc_ah(THREAD, bu); objArrayOop au = oopFactory::new_objArray(mu_kh(), MemoryService::num_memory_pools(), CHECK_NH); objArrayHandle usage_after_gc_ah(THREAD, au); for (int i = 0; i < MemoryService::num_memory_pools(); i++) { Handle before_usage = MemoryService::create_MemoryUsage_obj(gcStatInfo->before_gc_usage_for_pool(i), CHECK_NH); Handle after_usage; MemoryUsage u = gcStatInfo->after_gc_usage_for_pool(i); if (u.max_size() == 0 && u.used() > 0) { // If max size == 0, this pool is a survivor space. // Set max size = -1 since the pools will be swapped after GC. MemoryUsage usage(u.init_size(), u.used(), u.committed(), (size_t)-1); after_usage = MemoryService::create_MemoryUsage_obj(usage, CHECK_NH); } else { after_usage = MemoryService::create_MemoryUsage_obj(u, CHECK_NH); } usage_before_gc_ah->obj_at_put(i, before_usage()); usage_after_gc_ah->obj_at_put(i, after_usage()); } // Current implementation only has 1 attribute (number of GC threads) // The type is 'I' objArrayOop extra_args_array = oopFactory::new_objArray(SystemDictionary::Integer_klass(), 1, CHECK_NH); objArrayHandle extra_array (THREAD, extra_args_array); Klass* itKlass = SystemDictionary::Integer_klass(); instanceKlassHandle intK(THREAD, itKlass); instanceHandle extra_arg_val = intK->allocate_instance_handle(CHECK_NH); { JavaValue res(T_VOID); JavaCallArguments argsInt; argsInt.push_oop(extra_arg_val); argsInt.push_int(gcManager->num_gc_threads()); JavaCalls::call_special(&res, intK, vmSymbols::object_initializer_name(), vmSymbols::int_void_signature(), &argsInt, CHECK_NH); } extra_array->obj_at_put(0,extra_arg_val()); Klass* gcInfoklass = Management::com_sun_management_GcInfo_klass(CHECK_NH); instanceKlassHandle ik(THREAD, gcInfoklass); Handle gcInfo_instance = ik->allocate_instance_handle(CHECK_NH); JavaValue constructor_result(T_VOID); JavaCallArguments constructor_args(16); constructor_args.push_oop(gcInfo_instance); constructor_args.push_oop(getGcInfoBuilder(gcManager,THREAD)); constructor_args.push_long(gcStatInfo->gc_index()); constructor_args.push_long(Management::ticks_to_ms(gcStatInfo->start_time())); constructor_args.push_long(Management::ticks_to_ms(gcStatInfo->end_time())); constructor_args.push_oop(usage_before_gc_ah); constructor_args.push_oop(usage_after_gc_ah); constructor_args.push_oop(extra_array); JavaCalls::call_special(&constructor_result, ik, vmSymbols::object_initializer_name(), vmSymbols::com_sun_management_GcInfo_constructor_signature(), &constructor_args, CHECK_NH); return Handle(gcInfo_instance()); }