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