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