1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/services/lowMemoryDetector.hpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,285 @@ 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 +// Low Memory Detection Support 1.29 +// Two memory alarms in the JDK (we called them sensors). 1.30 +// - Heap memory sensor 1.31 +// - Non-heap memory sensor 1.32 +// When the VM detects if the memory usage of a memory pool has reached 1.33 +// or exceeded its threshold, it will trigger the sensor for the type 1.34 +// of the memory pool (heap or nonheap or both). 1.35 +// 1.36 +// If threshold == -1, no low memory detection is supported and 1.37 +// the threshold value is not allowed to be changed. 1.38 +// If threshold == 0, no low memory detection is performed for 1.39 +// that memory pool. The threshold can be set to any non-negative 1.40 +// value. 1.41 +// 1.42 +// The default threshold of the Hotspot memory pools are: 1.43 +// Eden space -1 1.44 +// Survivor space 1 -1 1.45 +// Survivor space 2 -1 1.46 +// Old generation 0 1.47 +// Perm generation 0 1.48 +// CodeCache 0 1.49 +// 1.50 +// For heap memory, detection will be performed when GC finishes 1.51 +// and also in the slow path allocation. 1.52 +// For Code cache, detection will be performed in the allocation 1.53 +// and deallocation. 1.54 +// 1.55 +// May need to deal with hysteresis effect. 1.56 +// 1.57 + 1.58 +class LowMemoryDetectorThread; 1.59 +class OopClosure; 1.60 +class MemoryPool; 1.61 + 1.62 +class ThresholdSupport : public CHeapObj { 1.63 + private: 1.64 + bool _support_high_threshold; 1.65 + bool _support_low_threshold; 1.66 + size_t _high_threshold; 1.67 + size_t _low_threshold; 1.68 + public: 1.69 + ThresholdSupport(bool support_high, bool support_low) { 1.70 + _support_high_threshold = support_high; 1.71 + _support_low_threshold = support_low; 1.72 + _high_threshold = 0; 1.73 + _low_threshold= 0; 1.74 + } 1.75 + 1.76 + size_t high_threshold() const { return _high_threshold; } 1.77 + size_t low_threshold() const { return _low_threshold; } 1.78 + bool is_high_threshold_supported() { return _support_high_threshold; } 1.79 + bool is_low_threshold_supported() { return _support_low_threshold; } 1.80 + 1.81 + bool is_high_threshold_crossed(MemoryUsage usage) { 1.82 + if (_support_high_threshold && _high_threshold > 0) { 1.83 + return (usage.used() >= _high_threshold); 1.84 + } 1.85 + return false; 1.86 + } 1.87 + bool is_low_threshold_crossed(MemoryUsage usage) { 1.88 + if (_support_low_threshold && _low_threshold > 0) { 1.89 + return (usage.used() < _low_threshold); 1.90 + } 1.91 + return false; 1.92 + } 1.93 + 1.94 + size_t set_high_threshold(size_t new_threshold) { 1.95 + assert(_support_high_threshold, "can only be set if supported"); 1.96 + assert(new_threshold >= _low_threshold, "new_threshold must be >= _low_threshold"); 1.97 + size_t prev = _high_threshold; 1.98 + _high_threshold = new_threshold; 1.99 + return prev; 1.100 + } 1.101 + 1.102 + size_t set_low_threshold(size_t new_threshold) { 1.103 + assert(_support_low_threshold, "can only be set if supported"); 1.104 + assert(new_threshold <= _high_threshold, "new_threshold must be <= _high_threshold"); 1.105 + size_t prev = _low_threshold; 1.106 + _low_threshold = new_threshold; 1.107 + return prev; 1.108 + } 1.109 +}; 1.110 + 1.111 +class SensorInfo : public CHeapObj { 1.112 +private: 1.113 + instanceOop _sensor_obj; 1.114 + bool _sensor_on; 1.115 + size_t _sensor_count; 1.116 + 1.117 + // before the actual sensor on flag and sensor count are set 1.118 + // we maintain the number of pending triggers and clears. 1.119 + // _pending_trigger_count means the number of pending triggers 1.120 + // and the sensor count should be incremented by the same number. 1.121 + 1.122 + int _pending_trigger_count; 1.123 + 1.124 + // _pending_clear_count takes precedence if it's > 0 which 1.125 + // indicates the resulting sensor will be off 1.126 + // Sensor trigger requests will reset this clear count to 1.127 + // indicate the resulting flag should be on. 1.128 + 1.129 + int _pending_clear_count; 1.130 + 1.131 + MemoryUsage _usage; 1.132 + 1.133 + void clear(int count, TRAPS); 1.134 + void trigger(int count, TRAPS); 1.135 +public: 1.136 + SensorInfo(); 1.137 + void set_sensor(instanceOop sensor) { 1.138 + assert(_sensor_obj == NULL, "Should be set only once"); 1.139 + _sensor_obj = sensor; 1.140 + } 1.141 + 1.142 + bool has_pending_requests() { 1.143 + return (_pending_trigger_count > 0 || _pending_clear_count > 0); 1.144 + } 1.145 + 1.146 + int pending_trigger_count() { return _pending_trigger_count; } 1.147 + int pending_clear_count() { return _pending_clear_count; } 1.148 + 1.149 + // When this method is used, the memory usage is monitored 1.150 + // as a gauge attribute. High and low thresholds are designed 1.151 + // to provide a hysteresis mechanism to avoid repeated triggering 1.152 + // of notifications when the attribute value makes small oscillations 1.153 + // around the high or low threshold value. 1.154 + // 1.155 + // The sensor will be triggered if: 1.156 + // (1) the usage is crossing above the high threshold and 1.157 + // the sensor is currently off and no pending 1.158 + // trigger requests; or 1.159 + // (2) the usage is crossing above the high threshold and 1.160 + // the sensor will be off (i.e. sensor is currently on 1.161 + // and has pending clear requests). 1.162 + // 1.163 + // Subsequent crossings of the high threshold value do not cause 1.164 + // any triggers unless the usage becomes less than the low threshold. 1.165 + // 1.166 + // The sensor will be cleared if: 1.167 + // (1) the usage is crossing below the low threshold and 1.168 + // the sensor is currently on and no pending 1.169 + // clear requests; or 1.170 + // (2) the usage is crossing below the low threshold and 1.171 + // the sensor will be on (i.e. sensor is currently off 1.172 + // and has pending trigger requests). 1.173 + // 1.174 + // Subsequent crossings of the low threshold value do not cause 1.175 + // any clears unless the usage becomes greater than or equal 1.176 + // to the high threshold. 1.177 + // 1.178 + // If the current level is between high and low threhsold, no change. 1.179 + // 1.180 + void set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* high_low_threshold); 1.181 + 1.182 + // When this method is used, the memory usage is monitored as a 1.183 + // simple counter attribute. The sensor will be triggered 1.184 + // whenever the usage is crossing the threshold to keep track 1.185 + // of the number of times the VM detects such a condition occurs. 1.186 + // 1.187 + // The sensor will be triggered if: 1.188 + // - the usage is crossing above the high threshold regardless 1.189 + // of the current sensor state. 1.190 + // 1.191 + // The sensor will be cleared if: 1.192 + // (1) the usage is crossing below the low threshold and 1.193 + // the sensor is currently on; or 1.194 + // (2) the usage is crossing below the low threshold and 1.195 + // the sensor will be on (i.e. sensor is currently off 1.196 + // and has pending trigger requests). 1.197 + // 1.198 + void set_counter_sensor_level(MemoryUsage usage, ThresholdSupport* counter_threshold); 1.199 + 1.200 + void process_pending_requests(TRAPS); 1.201 + void oops_do(OopClosure* f); 1.202 + 1.203 +#ifndef PRODUCT 1.204 + // printing on default output stream; 1.205 + void print(); 1.206 +#endif // PRODUCT 1.207 +}; 1.208 + 1.209 +class LowMemoryDetector : public AllStatic { 1.210 +friend class LowMemoryDetectorDisabler; 1.211 +private: 1.212 + // true if any collected heap has low memory detection enabled 1.213 + static volatile bool _enabled_for_collected_pools; 1.214 + // > 0 if temporary disabed 1.215 + static volatile jint _disabled_count; 1.216 + 1.217 + static LowMemoryDetectorThread* _detector_thread; 1.218 + static void low_memory_detector_thread_entry(JavaThread* thread, TRAPS); 1.219 + static void check_memory_usage(); 1.220 + static bool has_pending_requests(); 1.221 + static bool temporary_disabled() { return _disabled_count > 0; } 1.222 + static void disable() { Atomic::inc(&_disabled_count); } 1.223 + static void enable() { Atomic::dec(&_disabled_count); } 1.224 + 1.225 +public: 1.226 + static void initialize(); 1.227 + static void detect_low_memory(); 1.228 + static void detect_low_memory(MemoryPool* pool); 1.229 + static void detect_after_gc_memory(MemoryPool* pool); 1.230 + 1.231 + static bool is_enabled(MemoryPool* pool) { 1.232 + // low memory detection is enabled for collected memory pools 1.233 + // iff one of the collected memory pool has a sensor and the 1.234 + // threshold set non-zero 1.235 + if (pool->usage_sensor() == NULL) { 1.236 + return false; 1.237 + } else { 1.238 + ThresholdSupport* threshold_support = pool->usage_threshold(); 1.239 + return (threshold_support->is_high_threshold_supported() ? 1.240 + (threshold_support->high_threshold() > 0) : false); 1.241 + } 1.242 + } 1.243 + 1.244 + // indicates if low memory detection is enabled for any collected 1.245 + // memory pools 1.246 + static inline bool is_enabled_for_collected_pools() { 1.247 + return !temporary_disabled() && _enabled_for_collected_pools; 1.248 + } 1.249 + 1.250 + // recompute enabled flag 1.251 + static void recompute_enabled_for_collected_pools(); 1.252 + 1.253 + // low memory detection for collected memory pools. 1.254 + static inline void detect_low_memory_for_collected_pools() { 1.255 + // no-op if low memory detection not enabled 1.256 + if (!is_enabled_for_collected_pools()) { 1.257 + return; 1.258 + } 1.259 + int num_memory_pools = MemoryService::num_memory_pools(); 1.260 + for (int i=0; i<num_memory_pools; i++) { 1.261 + MemoryPool* pool = MemoryService::get_memory_pool(i); 1.262 + 1.263 + // if low memory detection is enabled then check if the 1.264 + // current used exceeds the high threshold 1.265 + if (pool->is_collected_pool() && is_enabled(pool)) { 1.266 + size_t used = pool->used_in_bytes(); 1.267 + size_t high = pool->usage_threshold()->high_threshold(); 1.268 + if (used > high) { 1.269 + detect_low_memory(pool); 1.270 + } 1.271 + } 1.272 + } 1.273 + } 1.274 + 1.275 +}; 1.276 + 1.277 +class LowMemoryDetectorDisabler: public StackObj { 1.278 +public: 1.279 + LowMemoryDetectorDisabler() 1.280 + { 1.281 + LowMemoryDetector::disable(); 1.282 + } 1.283 + ~LowMemoryDetectorDisabler() 1.284 + { 1.285 + assert(LowMemoryDetector::temporary_disabled(), "should be disabled!"); 1.286 + LowMemoryDetector::enable(); 1.287 + } 1.288 +};