1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/services/lowMemoryDetector.cpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,422 @@ 1.4 +/* 1.5 + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +# include "incls/_precompiled.incl" 1.29 +# include "incls/_lowMemoryDetector.cpp.incl" 1.30 + 1.31 +LowMemoryDetectorThread* LowMemoryDetector::_detector_thread = NULL; 1.32 +volatile bool LowMemoryDetector::_enabled_for_collected_pools = false; 1.33 +volatile jint LowMemoryDetector::_disabled_count = 0; 1.34 + 1.35 +void LowMemoryDetector::initialize() { 1.36 + EXCEPTION_MARK; 1.37 + 1.38 + instanceKlassHandle klass (THREAD, SystemDictionary::thread_klass()); 1.39 + instanceHandle thread_oop = klass->allocate_instance_handle(CHECK); 1.40 + 1.41 + const char thread_name[] = "Low Memory Detector"; 1.42 + Handle string = java_lang_String::create_from_str(thread_name, CHECK); 1.43 + 1.44 + // Initialize thread_oop to put it into the system threadGroup 1.45 + Handle thread_group (THREAD, Universe::system_thread_group()); 1.46 + JavaValue result(T_VOID); 1.47 + JavaCalls::call_special(&result, thread_oop, 1.48 + klass, 1.49 + vmSymbolHandles::object_initializer_name(), 1.50 + vmSymbolHandles::threadgroup_string_void_signature(), 1.51 + thread_group, 1.52 + string, 1.53 + CHECK); 1.54 + 1.55 + { 1.56 + MutexLocker mu(Threads_lock); 1.57 + _detector_thread = new LowMemoryDetectorThread(&low_memory_detector_thread_entry); 1.58 + 1.59 + // At this point it may be possible that no osthread was created for the 1.60 + // JavaThread due to lack of memory. We would have to throw an exception 1.61 + // in that case. However, since this must work and we do not allow 1.62 + // exceptions anyway, check and abort if this fails. 1.63 + if (_detector_thread == NULL || _detector_thread->osthread() == NULL) { 1.64 + vm_exit_during_initialization("java.lang.OutOfMemoryError", 1.65 + "unable to create new native thread"); 1.66 + } 1.67 + 1.68 + java_lang_Thread::set_thread(thread_oop(), _detector_thread); 1.69 + java_lang_Thread::set_priority(thread_oop(), NearMaxPriority); 1.70 + java_lang_Thread::set_daemon(thread_oop()); 1.71 + _detector_thread->set_threadObj(thread_oop()); 1.72 + 1.73 + Threads::add(_detector_thread); 1.74 + Thread::start(_detector_thread); 1.75 + } 1.76 +} 1.77 + 1.78 +bool LowMemoryDetector::has_pending_requests() { 1.79 + assert(LowMemory_lock->owned_by_self(), "Must own LowMemory_lock"); 1.80 + bool has_requests = false; 1.81 + int num_memory_pools = MemoryService::num_memory_pools(); 1.82 + for (int i = 0; i < num_memory_pools; i++) { 1.83 + MemoryPool* pool = MemoryService::get_memory_pool(i); 1.84 + SensorInfo* sensor = pool->usage_sensor(); 1.85 + if (sensor != NULL) { 1.86 + has_requests = has_requests || sensor->has_pending_requests(); 1.87 + } 1.88 + 1.89 + SensorInfo* gc_sensor = pool->gc_usage_sensor(); 1.90 + if (gc_sensor != NULL) { 1.91 + has_requests = has_requests || gc_sensor->has_pending_requests(); 1.92 + } 1.93 + } 1.94 + return has_requests; 1.95 +} 1.96 + 1.97 +void LowMemoryDetector::low_memory_detector_thread_entry(JavaThread* jt, TRAPS) { 1.98 + while (true) { 1.99 + bool sensors_changed = false; 1.100 + 1.101 + { 1.102 + // _no_safepoint_check_flag is used here as LowMemory_lock is a 1.103 + // special lock and the VMThread may acquire this lock at safepoint. 1.104 + // Need state transition ThreadBlockInVM so that this thread 1.105 + // will be handled by safepoint correctly when this thread is 1.106 + // notified at a safepoint. 1.107 + 1.108 + // This ThreadBlockInVM object is not also considered to be 1.109 + // suspend-equivalent because LowMemoryDetector threads are 1.110 + // not visible to external suspension. 1.111 + 1.112 + ThreadBlockInVM tbivm(jt); 1.113 + 1.114 + MutexLockerEx ml(LowMemory_lock, Mutex::_no_safepoint_check_flag); 1.115 + while (!(sensors_changed = has_pending_requests())) { 1.116 + // wait until one of the sensors has pending requests 1.117 + LowMemory_lock->wait(Mutex::_no_safepoint_check_flag); 1.118 + } 1.119 + } 1.120 + 1.121 + { 1.122 + ResourceMark rm(THREAD); 1.123 + HandleMark hm(THREAD); 1.124 + 1.125 + // No need to hold LowMemory_lock to call out to Java 1.126 + int num_memory_pools = MemoryService::num_memory_pools(); 1.127 + for (int i = 0; i < num_memory_pools; i++) { 1.128 + MemoryPool* pool = MemoryService::get_memory_pool(i); 1.129 + SensorInfo* sensor = pool->usage_sensor(); 1.130 + SensorInfo* gc_sensor = pool->gc_usage_sensor(); 1.131 + if (sensor != NULL && sensor->has_pending_requests()) { 1.132 + sensor->process_pending_requests(CHECK); 1.133 + } 1.134 + if (gc_sensor != NULL && gc_sensor->has_pending_requests()) { 1.135 + gc_sensor->process_pending_requests(CHECK); 1.136 + } 1.137 + } 1.138 + } 1.139 + } 1.140 +} 1.141 + 1.142 +// This method could be called from any Java threads 1.143 +// and also VMThread. 1.144 +void LowMemoryDetector::detect_low_memory() { 1.145 + MutexLockerEx ml(LowMemory_lock, Mutex::_no_safepoint_check_flag); 1.146 + 1.147 + bool has_pending_requests = false; 1.148 + int num_memory_pools = MemoryService::num_memory_pools(); 1.149 + for (int i = 0; i < num_memory_pools; i++) { 1.150 + MemoryPool* pool = MemoryService::get_memory_pool(i); 1.151 + SensorInfo* sensor = pool->usage_sensor(); 1.152 + if (sensor != NULL && 1.153 + pool->usage_threshold()->is_high_threshold_supported() && 1.154 + pool->usage_threshold()->high_threshold() != 0) { 1.155 + MemoryUsage usage = pool->get_memory_usage(); 1.156 + sensor->set_gauge_sensor_level(usage, 1.157 + pool->usage_threshold()); 1.158 + has_pending_requests = has_pending_requests || sensor->has_pending_requests(); 1.159 + } 1.160 + } 1.161 + 1.162 + if (has_pending_requests) { 1.163 + LowMemory_lock->notify_all(); 1.164 + } 1.165 +} 1.166 + 1.167 +// This method could be called from any Java threads 1.168 +// and also VMThread. 1.169 +void LowMemoryDetector::detect_low_memory(MemoryPool* pool) { 1.170 + SensorInfo* sensor = pool->usage_sensor(); 1.171 + if (sensor == NULL || 1.172 + !pool->usage_threshold()->is_high_threshold_supported() || 1.173 + pool->usage_threshold()->high_threshold() == 0) { 1.174 + return; 1.175 + } 1.176 + 1.177 + { 1.178 + MutexLockerEx ml(LowMemory_lock, Mutex::_no_safepoint_check_flag); 1.179 + 1.180 + MemoryUsage usage = pool->get_memory_usage(); 1.181 + sensor->set_gauge_sensor_level(usage, 1.182 + pool->usage_threshold()); 1.183 + if (sensor->has_pending_requests()) { 1.184 + // notify sensor state update 1.185 + LowMemory_lock->notify_all(); 1.186 + } 1.187 + } 1.188 +} 1.189 + 1.190 +// Only called by VMThread at GC time 1.191 +void LowMemoryDetector::detect_after_gc_memory(MemoryPool* pool) { 1.192 + SensorInfo* sensor = pool->gc_usage_sensor(); 1.193 + if (sensor == NULL || 1.194 + !pool->gc_usage_threshold()->is_high_threshold_supported() || 1.195 + pool->gc_usage_threshold()->high_threshold() == 0) { 1.196 + return; 1.197 + } 1.198 + 1.199 + { 1.200 + MutexLockerEx ml(LowMemory_lock, Mutex::_no_safepoint_check_flag); 1.201 + 1.202 + MemoryUsage usage = pool->get_last_collection_usage(); 1.203 + sensor->set_counter_sensor_level(usage, pool->gc_usage_threshold()); 1.204 + 1.205 + if (sensor->has_pending_requests()) { 1.206 + // notify sensor state update 1.207 + LowMemory_lock->notify_all(); 1.208 + } 1.209 + } 1.210 +} 1.211 + 1.212 +// recompute enabled flag 1.213 +void LowMemoryDetector::recompute_enabled_for_collected_pools() { 1.214 + bool enabled = false; 1.215 + int num_memory_pools = MemoryService::num_memory_pools(); 1.216 + for (int i=0; i<num_memory_pools; i++) { 1.217 + MemoryPool* pool = MemoryService::get_memory_pool(i); 1.218 + if (pool->is_collected_pool() && is_enabled(pool)) { 1.219 + enabled = true; 1.220 + break; 1.221 + } 1.222 + } 1.223 + _enabled_for_collected_pools = enabled; 1.224 +} 1.225 + 1.226 +SensorInfo::SensorInfo() { 1.227 + _sensor_obj = NULL; 1.228 + _sensor_on = false; 1.229 + _sensor_count = 0; 1.230 + _pending_trigger_count = 0; 1.231 + _pending_clear_count = 0; 1.232 +} 1.233 + 1.234 +// When this method is used, the memory usage is monitored 1.235 +// as a gauge attribute. Sensor notifications (trigger or 1.236 +// clear) is only emitted at the first time it crosses 1.237 +// a threshold. 1.238 +// 1.239 +// High and low thresholds are designed to provide a 1.240 +// hysteresis mechanism to avoid repeated triggering 1.241 +// of notifications when the attribute value makes small oscillations 1.242 +// around the high or low threshold value. 1.243 +// 1.244 +// The sensor will be triggered if: 1.245 +// (1) the usage is crossing above the high threshold and 1.246 +// the sensor is currently off and no pending 1.247 +// trigger requests; or 1.248 +// (2) the usage is crossing above the high threshold and 1.249 +// the sensor will be off (i.e. sensor is currently on 1.250 +// and has pending clear requests). 1.251 +// 1.252 +// Subsequent crossings of the high threshold value do not cause 1.253 +// any triggers unless the usage becomes less than the low threshold. 1.254 +// 1.255 +// The sensor will be cleared if: 1.256 +// (1) the usage is crossing below the low threshold and 1.257 +// the sensor is currently on and no pending 1.258 +// clear requests; or 1.259 +// (2) the usage is crossing below the low threshold and 1.260 +// the sensor will be on (i.e. sensor is currently off 1.261 +// and has pending trigger requests). 1.262 +// 1.263 +// Subsequent crossings of the low threshold value do not cause 1.264 +// any clears unless the usage becomes greater than or equal 1.265 +// to the high threshold. 1.266 +// 1.267 +// If the current level is between high and low threhsold, no change. 1.268 +// 1.269 +void SensorInfo::set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* high_low_threshold) { 1.270 + assert(high_low_threshold->is_high_threshold_supported(), "just checking"); 1.271 + 1.272 + bool is_over_high = high_low_threshold->is_high_threshold_crossed(usage); 1.273 + bool is_below_low = high_low_threshold->is_low_threshold_crossed(usage); 1.274 + 1.275 + assert(!(is_over_high && is_below_low), "Can't be both true"); 1.276 + 1.277 + if (is_over_high && 1.278 + ((!_sensor_on && _pending_trigger_count == 0) || 1.279 + _pending_clear_count > 0)) { 1.280 + // low memory detected and need to increment the trigger pending count 1.281 + // if the sensor is off or will be off due to _pending_clear_ > 0 1.282 + // Request to trigger the sensor 1.283 + _pending_trigger_count++; 1.284 + _usage = usage; 1.285 + 1.286 + if (_pending_clear_count > 0) { 1.287 + // non-zero pending clear requests indicates that there are 1.288 + // pending requests to clear this sensor. 1.289 + // This trigger request needs to clear this clear count 1.290 + // since the resulting sensor flag should be on. 1.291 + _pending_clear_count = 0; 1.292 + } 1.293 + } else if (is_below_low && 1.294 + ((_sensor_on && _pending_clear_count == 0) || 1.295 + (_pending_trigger_count > 0 && _pending_clear_count == 0))) { 1.296 + // memory usage returns below the threshold 1.297 + // Request to clear the sensor if the sensor is on or will be on due to 1.298 + // _pending_trigger_count > 0 and also no clear request 1.299 + _pending_clear_count++; 1.300 + } 1.301 +} 1.302 + 1.303 +// When this method is used, the memory usage is monitored as a 1.304 +// simple counter attribute. The sensor will be triggered 1.305 +// whenever the usage is crossing the threshold to keep track 1.306 +// of the number of times the VM detects such a condition occurs. 1.307 +// 1.308 +// High and low thresholds are designed to provide a 1.309 +// hysteresis mechanism to avoid repeated triggering 1.310 +// of notifications when the attribute value makes small oscillations 1.311 +// around the high or low threshold value. 1.312 +// 1.313 +// The sensor will be triggered if: 1.314 +// - the usage is crossing above the high threshold regardless 1.315 +// of the current sensor state. 1.316 +// 1.317 +// The sensor will be cleared if: 1.318 +// (1) the usage is crossing below the low threshold and 1.319 +// the sensor is currently on; or 1.320 +// (2) the usage is crossing below the low threshold and 1.321 +// the sensor will be on (i.e. sensor is currently off 1.322 +// and has pending trigger requests). 1.323 +void SensorInfo::set_counter_sensor_level(MemoryUsage usage, ThresholdSupport* counter_threshold) { 1.324 + assert(counter_threshold->is_high_threshold_supported(), "just checking"); 1.325 + 1.326 + bool is_over_high = counter_threshold->is_high_threshold_crossed(usage); 1.327 + bool is_below_low = counter_threshold->is_low_threshold_crossed(usage); 1.328 + 1.329 + assert(!(is_over_high && is_below_low), "Can't be both true"); 1.330 + 1.331 + if (is_over_high) { 1.332 + _pending_trigger_count++; 1.333 + _usage = usage; 1.334 + _pending_clear_count = 0; 1.335 + } else if (is_below_low && (_sensor_on || _pending_trigger_count > 0)) { 1.336 + _pending_clear_count++; 1.337 + } 1.338 +} 1.339 + 1.340 +void SensorInfo::oops_do(OopClosure* f) { 1.341 + f->do_oop((oop*) &_sensor_obj); 1.342 +} 1.343 + 1.344 +void SensorInfo::process_pending_requests(TRAPS) { 1.345 + if (!has_pending_requests()) { 1.346 + return; 1.347 + } 1.348 + 1.349 + int pending_count = pending_trigger_count(); 1.350 + if (pending_clear_count() > 0) { 1.351 + clear(pending_count, CHECK); 1.352 + } else { 1.353 + trigger(pending_count, CHECK); 1.354 + } 1.355 + 1.356 +} 1.357 + 1.358 +void SensorInfo::trigger(int count, TRAPS) { 1.359 + assert(count <= _pending_trigger_count, "just checking"); 1.360 + 1.361 + if (_sensor_obj != NULL) { 1.362 + klassOop k = Management::sun_management_Sensor_klass(CHECK); 1.363 + instanceKlassHandle sensorKlass (THREAD, k); 1.364 + Handle sensor_h(THREAD, _sensor_obj); 1.365 + Handle usage_h = MemoryService::create_MemoryUsage_obj(_usage, CHECK); 1.366 + 1.367 + JavaValue result(T_VOID); 1.368 + JavaCallArguments args(sensor_h); 1.369 + args.push_int((int) count); 1.370 + args.push_oop(usage_h); 1.371 + 1.372 + JavaCalls::call_virtual(&result, 1.373 + sensorKlass, 1.374 + vmSymbolHandles::trigger_name(), 1.375 + vmSymbolHandles::trigger_method_signature(), 1.376 + &args, 1.377 + CHECK); 1.378 + } 1.379 + 1.380 + { 1.381 + // Holds LowMemory_lock and update the sensor state 1.382 + MutexLockerEx ml(LowMemory_lock, Mutex::_no_safepoint_check_flag); 1.383 + _sensor_on = true; 1.384 + _sensor_count += count; 1.385 + _pending_trigger_count = _pending_trigger_count - count; 1.386 + } 1.387 +} 1.388 + 1.389 +void SensorInfo::clear(int count, TRAPS) { 1.390 + if (_sensor_obj != NULL) { 1.391 + klassOop k = Management::sun_management_Sensor_klass(CHECK); 1.392 + instanceKlassHandle sensorKlass (THREAD, k); 1.393 + Handle sensor(THREAD, _sensor_obj); 1.394 + 1.395 + JavaValue result(T_VOID); 1.396 + JavaCallArguments args(sensor); 1.397 + args.push_int((int) count); 1.398 + JavaCalls::call_virtual(&result, 1.399 + sensorKlass, 1.400 + vmSymbolHandles::clear_name(), 1.401 + vmSymbolHandles::int_void_signature(), 1.402 + &args, 1.403 + CHECK); 1.404 + } 1.405 + 1.406 + { 1.407 + // Holds LowMemory_lock and update the sensor state 1.408 + MutexLockerEx ml(LowMemory_lock, Mutex::_no_safepoint_check_flag); 1.409 + _sensor_on = false; 1.410 + _pending_clear_count = 0; 1.411 + _pending_trigger_count = _pending_trigger_count - count; 1.412 + } 1.413 +} 1.414 + 1.415 +//-------------------------------------------------------------- 1.416 +// Non-product code 1.417 + 1.418 +#ifndef PRODUCT 1.419 +void SensorInfo::print() { 1.420 + tty->print_cr("%s count = %ld pending_triggers = %ld pending_clears = %ld", 1.421 + (_sensor_on ? "on" : "off"), 1.422 + _sensor_count, _pending_trigger_count, _pending_clear_count); 1.423 +} 1.424 + 1.425 +#endif // PRODUCT