1 /* 2 * Copyright (c) 2003, 2017, 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 #include "precompiled.hpp" 26 #include "classfile/systemDictionary.hpp" 27 #include "classfile/vmSymbols.hpp" 28 #include "gc/shared/collectedHeap.hpp" 29 #include "gc/shared/gcServicabilitySupport.hpp" 30 #include "gc/shared/generation.hpp" 31 #include "logging/logConfiguration.hpp" 32 #include "memory/heap.hpp" 33 #include "memory/memRegion.hpp" 34 #include "oops/oop.inline.hpp" 35 #include "runtime/globals.hpp" 36 #include "runtime/javaCalls.hpp" 37 #include "services/classLoadingService.hpp" 38 #include "services/lowMemoryDetector.hpp" 39 #include "services/management.hpp" 40 #include "services/memoryManager.hpp" 41 #include "services/memoryPool.hpp" 42 #include "services/memoryService.hpp" 43 #include "utilities/growableArray.hpp" 44 #include "utilities/macros.hpp" 45 46 GrowableArray<MemoryPool*>* MemoryService::_pools_list = 47 new (ResourceObj::C_HEAP, mtInternal) GrowableArray<MemoryPool*>(init_pools_list_size, true); 48 GrowableArray<MemoryManager*>* MemoryService::_managers_list = 49 new (ResourceObj::C_HEAP, mtInternal) GrowableArray<MemoryManager*>(init_managers_list_size, true); 50 51 GCMemoryManager* MemoryService::_minor_gc_manager = NULL; 52 GCMemoryManager* MemoryService::_major_gc_manager = NULL; 53 MemoryManager* MemoryService::_code_cache_manager = NULL; 54 GrowableArray<MemoryPool*>* MemoryService::_code_heap_pools = 55 new (ResourceObj::C_HEAP, mtInternal) GrowableArray<MemoryPool*>(init_code_heap_pools_size, true); 56 MemoryPool* MemoryService::_metaspace_pool = NULL; 57 MemoryPool* MemoryService::_compressed_class_pool = NULL; 58 59 class GcThreadCountClosure: public ThreadClosure { 60 private: 61 int _count; 62 public: 63 GcThreadCountClosure() : _count(0) {}; 64 void do_thread(Thread* thread); 65 int count() { return _count; } 66 }; 67 68 void GcThreadCountClosure::do_thread(Thread* thread) { 69 _count++; 70 } 71 72 void MemoryService::set_universe_heap(CollectedHeap* heap) { 73 _minor_gc_manager = heap->servicability_support()->create_minor_gc_manager(); 74 _major_gc_manager = heap->servicability_support()->create_major_gc_manager(); 75 _managers_list->append(_minor_gc_manager); 76 _managers_list->append(_major_gc_manager); 77 78 heap->servicability_support()->add_memory_pools(_pools_list, 79 _minor_gc_manager, 80 _major_gc_manager); 81 82 // set the GC thread count 83 GcThreadCountClosure gctcc; 84 heap->gc_threads_do(&gctcc); 85 int count = gctcc.count(); 86 if (count > 0) { 87 _minor_gc_manager->set_num_gc_threads(count); 88 _major_gc_manager->set_num_gc_threads(count); 89 } 90 91 // All memory pools and memory managers are initialized. 92 // 93 _minor_gc_manager->initialize_gc_stat_info(); 94 _major_gc_manager->initialize_gc_stat_info(); 95 } 96 97 void MemoryService::add_code_heap_memory_pool(CodeHeap* heap, const char* name) { 98 // Create new memory pool for this heap 99 MemoryPool* code_heap_pool = new CodeHeapPool(heap, name, true /* support_usage_threshold */); 100 101 // Append to lists 102 _code_heap_pools->append(code_heap_pool); 103 _pools_list->append(code_heap_pool); 104 105 if (_code_cache_manager == NULL) { 106 // Create CodeCache memory manager 107 _code_cache_manager = MemoryManager::get_code_cache_memory_manager(); 108 _managers_list->append(_code_cache_manager); 109 } 110 111 _code_cache_manager->add_pool(code_heap_pool); 112 } 113 114 void MemoryService::add_metaspace_memory_pools() { 115 MemoryManager* mgr = MemoryManager::get_metaspace_memory_manager(); 116 117 _metaspace_pool = new MetaspacePool(); 118 mgr->add_pool(_metaspace_pool); 119 _pools_list->append(_metaspace_pool); 120 121 if (UseCompressedClassPointers) { 122 _compressed_class_pool = new CompressedKlassSpacePool(); 123 mgr->add_pool(_compressed_class_pool); 124 _pools_list->append(_compressed_class_pool); 125 } 126 127 _managers_list->append(mgr); 128 } 129 130 MemoryManager* MemoryService::get_memory_manager(instanceHandle mh) { 131 for (int i = 0; i < _managers_list->length(); i++) { 132 MemoryManager* mgr = _managers_list->at(i); 133 if (mgr->is_manager(mh)) { 134 return mgr; 135 } 136 } 137 return NULL; 138 } 139 140 MemoryPool* MemoryService::get_memory_pool(instanceHandle ph) { 141 for (int i = 0; i < _pools_list->length(); i++) { 142 MemoryPool* pool = _pools_list->at(i); 143 if (pool->is_pool(ph)) { 144 return pool; 145 } 146 } 147 return NULL; 148 } 149 150 void MemoryService::track_memory_usage() { 151 // Track the peak memory usage 152 for (int i = 0; i < _pools_list->length(); i++) { 153 MemoryPool* pool = _pools_list->at(i); 154 pool->record_peak_memory_usage(); 155 } 156 157 // Detect low memory 158 LowMemoryDetector::detect_low_memory(); 159 } 160 161 void MemoryService::track_memory_pool_usage(MemoryPool* pool) { 162 // Track the peak memory usage 163 pool->record_peak_memory_usage(); 164 165 // Detect low memory 166 if (LowMemoryDetector::is_enabled(pool)) { 167 LowMemoryDetector::detect_low_memory(pool); 168 } 169 } 170 171 void MemoryService::gc_begin(bool fullGC, bool recordGCBeginTime, 172 bool recordAccumulatedGCTime, 173 bool recordPreGCUsage, bool recordPeakUsage) { 174 175 GCMemoryManager* mgr; 176 if (fullGC) { 177 mgr = _major_gc_manager; 178 } else { 179 mgr = _minor_gc_manager; 180 } 181 assert(mgr->is_gc_memory_manager(), "Sanity check"); 182 mgr->gc_begin(recordGCBeginTime, recordPreGCUsage, recordAccumulatedGCTime); 183 184 // Track the peak memory usage when GC begins 185 if (recordPeakUsage) { 186 for (int i = 0; i < _pools_list->length(); i++) { 187 MemoryPool* pool = _pools_list->at(i); 188 pool->record_peak_memory_usage(); 189 } 190 } 191 } 192 193 void MemoryService::gc_end(bool fullGC, bool recordPostGCUsage, 194 bool recordAccumulatedGCTime, 195 bool recordGCEndTime, bool countCollection, 196 GCCause::Cause cause) { 197 198 GCMemoryManager* mgr; 199 if (fullGC) { 200 mgr = (GCMemoryManager*) _major_gc_manager; 201 } else { 202 mgr = (GCMemoryManager*) _minor_gc_manager; 203 } 204 assert(mgr->is_gc_memory_manager(), "Sanity check"); 205 206 // register the GC end statistics and memory usage 207 mgr->gc_end(recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime, 208 countCollection, cause); 209 } 210 211 void MemoryService::oops_do(OopClosure* f) { 212 int i; 213 214 for (i = 0; i < _pools_list->length(); i++) { 215 MemoryPool* pool = _pools_list->at(i); 216 pool->oops_do(f); 217 } 218 for (i = 0; i < _managers_list->length(); i++) { 219 MemoryManager* mgr = _managers_list->at(i); 220 mgr->oops_do(f); 221 } 222 } 223 224 bool MemoryService::set_verbose(bool verbose) { 225 MutexLocker m(Management_lock); 226 // verbose will be set to the previous value 227 if (verbose) { 228 LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(gc)); 229 } else { 230 LogConfiguration::configure_stdout(LogLevel::Off, true, LOG_TAGS(gc)); 231 } 232 ClassLoadingService::reset_trace_class_unloading(); 233 234 return verbose; 235 } 236 237 Handle MemoryService::create_MemoryUsage_obj(MemoryUsage usage, TRAPS) { 238 InstanceKlass* ik = Management::java_lang_management_MemoryUsage_klass(CHECK_NH); 239 240 instanceHandle obj = ik->allocate_instance_handle(CHECK_NH); 241 242 JavaValue result(T_VOID); 243 JavaCallArguments args(10); 244 args.push_oop(obj); // receiver 245 args.push_long(usage.init_size_as_jlong()); // Argument 1 246 args.push_long(usage.used_as_jlong()); // Argument 2 247 args.push_long(usage.committed_as_jlong()); // Argument 3 248 args.push_long(usage.max_size_as_jlong()); // Argument 4 249 250 JavaCalls::call_special(&result, 251 ik, 252 vmSymbols::object_initializer_name(), 253 vmSymbols::long_long_long_long_void_signature(), 254 &args, 255 CHECK_NH); 256 return obj; 257 } 258 259 // GC manager type depends on the type of Generation. Depending on the space 260 // availability and vm options the gc uses major gc manager or minor gc 261 // manager or both. The type of gc manager depends on the generation kind. 262 // For DefNew and ParNew generation doing scavenge gc uses minor gc manager (so 263 // _fullGC is set to false ) and for other generation kinds doing 264 // mark-sweep-compact uses major gc manager (so _fullGC is set to true). 265 TraceMemoryManagerStats::TraceMemoryManagerStats(Generation::Name kind, GCCause::Cause cause) { 266 switch (kind) { 267 case Generation::DefNew: 268 #if INCLUDE_ALL_GCS 269 case Generation::ParNew: 270 #endif // INCLUDE_ALL_GCS 271 _fullGC = false; 272 break; 273 case Generation::MarkSweepCompact: 274 #if INCLUDE_ALL_GCS 275 case Generation::ConcurrentMarkSweep: 276 #endif // INCLUDE_ALL_GCS 277 _fullGC = true; 278 break; 279 default: 280 _fullGC = false; 281 assert(false, "Unrecognized gc generation kind."); 282 } 283 // this has to be called in a stop the world pause and represent 284 // an entire gc pause, start to finish: 285 initialize(_fullGC, cause, true, true, true, true, true, true, true); 286 } 287 288 TraceMemoryManagerStats::TraceMemoryManagerStats(bool fullGC, 289 GCCause::Cause cause, 290 bool recordGCBeginTime, 291 bool recordPreGCUsage, 292 bool recordPeakUsage, 293 bool recordPostGCUsage, 294 bool recordAccumulatedGCTime, 295 bool recordGCEndTime, 296 bool countCollection) { 297 initialize(fullGC, cause, recordGCBeginTime, recordPreGCUsage, recordPeakUsage, 298 recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime, 299 countCollection); 300 } 301 302 // for a subclass to create then initialize an instance before invoking 303 // the MemoryService 304 void TraceMemoryManagerStats::initialize(bool fullGC, 305 GCCause::Cause cause, 306 bool recordGCBeginTime, 307 bool recordPreGCUsage, 308 bool recordPeakUsage, 309 bool recordPostGCUsage, 310 bool recordAccumulatedGCTime, 311 bool recordGCEndTime, 312 bool countCollection) { 313 _fullGC = fullGC; 314 _recordGCBeginTime = recordGCBeginTime; 315 _recordPreGCUsage = recordPreGCUsage; 316 _recordPeakUsage = recordPeakUsage; 317 _recordPostGCUsage = recordPostGCUsage; 318 _recordAccumulatedGCTime = recordAccumulatedGCTime; 319 _recordGCEndTime = recordGCEndTime; 320 _countCollection = countCollection; 321 _cause = cause; 322 323 MemoryService::gc_begin(_fullGC, _recordGCBeginTime, _recordAccumulatedGCTime, 324 _recordPreGCUsage, _recordPeakUsage); 325 } 326 327 TraceMemoryManagerStats::~TraceMemoryManagerStats() { 328 MemoryService::gc_end(_fullGC, _recordPostGCUsage, _recordAccumulatedGCTime, 329 _recordGCEndTime, _countCollection, _cause); 330 }