1 /* 2 * Copyright (c) 2003, 2018, 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 "logging/logConfiguration.hpp" 30 #include "memory/heap.hpp" 31 #include "memory/memRegion.hpp" 32 #include "oops/oop.inline.hpp" 33 #include "runtime/globals.hpp" 34 #include "runtime/handles.inline.hpp" 35 #include "runtime/javaCalls.hpp" 36 #include "services/classLoadingService.hpp" 37 #include "services/lowMemoryDetector.hpp" 38 #include "services/management.hpp" 39 #include "services/memoryManager.hpp" 40 #include "services/memoryPool.hpp" 41 #include "services/memoryService.hpp" 42 #include "utilities/growableArray.hpp" 43 #include "utilities/macros.hpp" 44 45 GrowableArray<MemoryPool*>* MemoryService::_pools_list = 46 new (ResourceObj::C_HEAP, mtInternal) GrowableArray<MemoryPool*>(init_pools_list_size, true); 47 GrowableArray<MemoryManager*>* MemoryService::_managers_list = 48 new (ResourceObj::C_HEAP, mtInternal) GrowableArray<MemoryManager*>(init_managers_list_size, true); 49 50 MemoryManager* MemoryService::_code_cache_manager = NULL; 51 GrowableArray<MemoryPool*>* MemoryService::_code_heap_pools = 52 new (ResourceObj::C_HEAP, mtInternal) GrowableArray<MemoryPool*>(init_code_heap_pools_size, true); 53 MemoryPool* MemoryService::_metaspace_pool = NULL; 54 MemoryPool* MemoryService::_compressed_class_pool = NULL; 55 56 class GcThreadCountClosure: public ThreadClosure { 57 private: 58 int _count; 59 public: 60 GcThreadCountClosure() : _count(0) {}; 61 void do_thread(Thread* thread); 62 int count() { return _count; } 63 }; 64 65 void GcThreadCountClosure::do_thread(Thread* thread) { 66 _count++; 67 } 68 69 void MemoryService::set_universe_heap(CollectedHeap* heap) { 70 ResourceMark rm; // For internal allocations in GrowableArray. 71 72 GrowableArray<MemoryPool*> gc_mem_pools = heap->memory_pools(); 73 _pools_list->appendAll(&gc_mem_pools); 74 75 // set the GC thread count 76 GcThreadCountClosure gctcc; 77 heap->gc_threads_do(&gctcc); 78 int count = gctcc.count(); 79 80 GrowableArray<GCMemoryManager*> gc_memory_managers = heap->memory_managers(); 81 for (int i = 0; i < gc_memory_managers.length(); i++) { 82 GCMemoryManager* gc_manager = gc_memory_managers.at(i); 83 84 if (count > 0) { 85 gc_manager->set_num_gc_threads(count); 86 } 87 gc_manager->initialize_gc_stat_info(); 88 _managers_list->append(gc_manager); 89 } 90 } 91 92 void MemoryService::add_code_heap_memory_pool(CodeHeap* heap, const char* name) { 93 // Create new memory pool for this heap 94 MemoryPool* code_heap_pool = new CodeHeapPool(heap, name, true /* support_usage_threshold */); 95 96 // Append to lists 97 _code_heap_pools->append(code_heap_pool); 98 _pools_list->append(code_heap_pool); 99 100 if (_code_cache_manager == NULL) { 101 // Create CodeCache memory manager 102 _code_cache_manager = MemoryManager::get_code_cache_memory_manager(); 103 _managers_list->append(_code_cache_manager); 104 } 105 106 _code_cache_manager->add_pool(code_heap_pool); 107 } 108 109 void MemoryService::add_metaspace_memory_pools() { 110 MemoryManager* mgr = MemoryManager::get_metaspace_memory_manager(); 111 112 _metaspace_pool = new MetaspacePool(); 113 mgr->add_pool(_metaspace_pool); 114 _pools_list->append(_metaspace_pool); 115 116 if (UseCompressedClassPointers) { 117 _compressed_class_pool = new CompressedKlassSpacePool(); 118 mgr->add_pool(_compressed_class_pool); 119 _pools_list->append(_compressed_class_pool); 120 } 121 122 _managers_list->append(mgr); 123 } 124 125 MemoryManager* MemoryService::get_memory_manager(instanceHandle mh) { 126 for (int i = 0; i < _managers_list->length(); i++) { 127 MemoryManager* mgr = _managers_list->at(i); 128 if (mgr->is_manager(mh)) { 129 return mgr; 130 } 131 } 132 return NULL; 133 } 134 135 MemoryPool* MemoryService::get_memory_pool(instanceHandle ph) { 136 for (int i = 0; i < _pools_list->length(); i++) { 137 MemoryPool* pool = _pools_list->at(i); 138 if (pool->is_pool(ph)) { 139 return pool; 140 } 141 } 142 return NULL; 143 } 144 145 void MemoryService::track_memory_usage() { 146 // Track the peak memory usage 147 for (int i = 0; i < _pools_list->length(); i++) { 148 MemoryPool* pool = _pools_list->at(i); 149 pool->record_peak_memory_usage(); 150 } 151 152 // Detect low memory 153 LowMemoryDetector::detect_low_memory(); 154 } 155 156 void MemoryService::track_memory_pool_usage(MemoryPool* pool) { 157 // Track the peak memory usage 158 pool->record_peak_memory_usage(); 159 160 // Detect low memory 161 if (LowMemoryDetector::is_enabled(pool)) { 162 LowMemoryDetector::detect_low_memory(pool); 163 } 164 } 165 166 void MemoryService::gc_begin(GCMemoryManager* manager, bool recordGCBeginTime, 167 bool recordAccumulatedGCTime, 168 bool recordPreGCUsage, bool recordPeakUsage) { 169 170 manager->gc_begin(recordGCBeginTime, recordPreGCUsage, recordAccumulatedGCTime); 171 172 // Track the peak memory usage when GC begins 173 if (recordPeakUsage) { 174 for (int i = 0; i < _pools_list->length(); i++) { 175 MemoryPool* pool = _pools_list->at(i); 176 pool->record_peak_memory_usage(); 177 } 178 } 179 } 180 181 void MemoryService::gc_end(GCMemoryManager* manager, bool recordPostGCUsage, 182 bool recordAccumulatedGCTime, 183 bool recordGCEndTime, bool countCollection, 184 GCCause::Cause cause) { 185 // register the GC end statistics and memory usage 186 manager->gc_end(recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime, 187 countCollection, cause); 188 } 189 190 void MemoryService::oops_do(OopClosure* f) { 191 int i; 192 193 for (i = 0; i < _pools_list->length(); i++) { 194 MemoryPool* pool = _pools_list->at(i); 195 pool->oops_do(f); 196 } 197 for (i = 0; i < _managers_list->length(); i++) { 198 MemoryManager* mgr = _managers_list->at(i); 199 mgr->oops_do(f); 200 } 201 } 202 203 bool MemoryService::set_verbose(bool verbose) { 204 MutexLocker m(Management_lock); 205 // verbose will be set to the previous value 206 if (verbose) { 207 LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(gc)); 208 } else { 209 LogConfiguration::configure_stdout(LogLevel::Off, true, LOG_TAGS(gc)); 210 } 211 ClassLoadingService::reset_trace_class_unloading(); 212 213 return verbose; 214 } 215 216 Handle MemoryService::create_MemoryUsage_obj(MemoryUsage usage, TRAPS) { 217 InstanceKlass* ik = Management::java_lang_management_MemoryUsage_klass(CHECK_NH); 218 219 instanceHandle obj = ik->allocate_instance_handle(CHECK_NH); 220 221 JavaValue result(T_VOID); 222 JavaCallArguments args(10); 223 args.push_oop(obj); // receiver 224 args.push_long(usage.init_size_as_jlong()); // Argument 1 225 args.push_long(usage.used_as_jlong()); // Argument 2 226 args.push_long(usage.committed_as_jlong()); // Argument 3 227 args.push_long(usage.max_size_as_jlong()); // Argument 4 228 229 JavaCalls::call_special(&result, 230 ik, 231 vmSymbols::object_initializer_name(), 232 vmSymbols::long_long_long_long_void_signature(), 233 &args, 234 CHECK_NH); 235 return obj; 236 } 237 238 TraceMemoryManagerStats::TraceMemoryManagerStats(GCMemoryManager* gc_memory_manager, 239 GCCause::Cause cause, 240 bool recordGCBeginTime, 241 bool recordPreGCUsage, 242 bool recordPeakUsage, 243 bool recordPostGCUsage, 244 bool recordAccumulatedGCTime, 245 bool recordGCEndTime, 246 bool countCollection) { 247 initialize(gc_memory_manager, cause, recordGCBeginTime, recordPreGCUsage, recordPeakUsage, 248 recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime, 249 countCollection); 250 } 251 252 // for a subclass to create then initialize an instance before invoking 253 // the MemoryService 254 void TraceMemoryManagerStats::initialize(GCMemoryManager* gc_memory_manager, 255 GCCause::Cause cause, 256 bool recordGCBeginTime, 257 bool recordPreGCUsage, 258 bool recordPeakUsage, 259 bool recordPostGCUsage, 260 bool recordAccumulatedGCTime, 261 bool recordGCEndTime, 262 bool countCollection) { 263 _gc_memory_manager = gc_memory_manager; 264 _recordGCBeginTime = recordGCBeginTime; 265 _recordPreGCUsage = recordPreGCUsage; 266 _recordPeakUsage = recordPeakUsage; 267 _recordPostGCUsage = recordPostGCUsage; 268 _recordAccumulatedGCTime = recordAccumulatedGCTime; 269 _recordGCEndTime = recordGCEndTime; 270 _countCollection = countCollection; 271 _cause = cause; 272 273 MemoryService::gc_begin(_gc_memory_manager, _recordGCBeginTime, _recordAccumulatedGCTime, 274 _recordPreGCUsage, _recordPeakUsage); 275 } 276 277 TraceMemoryManagerStats::~TraceMemoryManagerStats() { 278 MemoryService::gc_end(_gc_memory_manager, _recordPostGCUsage, _recordAccumulatedGCTime, 279 _recordGCEndTime, _countCollection, _cause); 280 }