1 /* 2 * Copyright (c) 2003, 2010, 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 #ifndef SHARE_VM_SERVICES_LOWMEMORYDETECTOR_HPP 26 #define SHARE_VM_SERVICES_LOWMEMORYDETECTOR_HPP 27 28 #include "memory/allocation.hpp" 29 #include "services/memoryPool.hpp" 30 #include "services/memoryService.hpp" 31 32 // Low Memory Detection Support 33 // Two memory alarms in the JDK (we called them sensors). 34 // - Heap memory sensor 35 // - Non-heap memory sensor 36 // When the VM detects if the memory usage of a memory pool has reached 37 // or exceeded its threshold, it will trigger the sensor for the type 38 // of the memory pool (heap or nonheap or both). 39 // 40 // If threshold == -1, no low memory detection is supported and 41 // the threshold value is not allowed to be changed. 42 // If threshold == 0, no low memory detection is performed for 43 // that memory pool. The threshold can be set to any non-negative 44 // value. 45 // 46 // The default threshold of the Hotspot memory pools are: 47 // Eden space -1 48 // Survivor space 1 -1 49 // Survivor space 2 -1 50 // Old generation 0 51 // Perm generation 0 52 // CodeCache 0 53 // 54 // For heap memory, detection will be performed when GC finishes 55 // and also in the slow path allocation. 56 // For Code cache, detection will be performed in the allocation 57 // and deallocation. 58 // 59 // May need to deal with hysteresis effect. 60 // 61 62 class LowMemoryDetectorThread; 63 class OopClosure; 64 class MemoryPool; 65 66 class ThresholdSupport : public CHeapObj { 67 private: 68 bool _support_high_threshold; 69 bool _support_low_threshold; 70 size_t _high_threshold; 71 size_t _low_threshold; 72 public: 73 ThresholdSupport(bool support_high, bool support_low) { 74 _support_high_threshold = support_high; 75 _support_low_threshold = support_low; 76 _high_threshold = 0; 77 _low_threshold= 0; 78 } 79 80 size_t high_threshold() const { return _high_threshold; } 81 size_t low_threshold() const { return _low_threshold; } 82 bool is_high_threshold_supported() { return _support_high_threshold; } 83 bool is_low_threshold_supported() { return _support_low_threshold; } 84 85 bool is_high_threshold_crossed(MemoryUsage usage) { 86 if (_support_high_threshold && _high_threshold > 0) { 87 return (usage.used() >= _high_threshold); 88 } 89 return false; 90 } 91 bool is_low_threshold_crossed(MemoryUsage usage) { 92 if (_support_low_threshold && _low_threshold > 0) { 93 return (usage.used() < _low_threshold); 94 } 95 return false; 96 } 97 98 size_t set_high_threshold(size_t new_threshold) { 99 assert(_support_high_threshold, "can only be set if supported"); 100 assert(new_threshold >= _low_threshold, "new_threshold must be >= _low_threshold"); 101 size_t prev = _high_threshold; 102 _high_threshold = new_threshold; 103 return prev; 104 } 105 106 size_t set_low_threshold(size_t new_threshold) { 107 assert(_support_low_threshold, "can only be set if supported"); 108 assert(new_threshold <= _high_threshold, "new_threshold must be <= _high_threshold"); 109 size_t prev = _low_threshold; 110 _low_threshold = new_threshold; 111 return prev; 112 } 113 }; 114 115 class SensorInfo : public CHeapObj { 116 private: 117 instanceOop _sensor_obj; 118 bool _sensor_on; 119 size_t _sensor_count; 120 121 // before the actual sensor on flag and sensor count are set 122 // we maintain the number of pending triggers and clears. 123 // _pending_trigger_count means the number of pending triggers 124 // and the sensor count should be incremented by the same number. 125 126 int _pending_trigger_count; 127 128 // _pending_clear_count takes precedence if it's > 0 which 129 // indicates the resulting sensor will be off 130 // Sensor trigger requests will reset this clear count to 131 // indicate the resulting flag should be on. 132 133 int _pending_clear_count; 134 135 MemoryUsage _usage; 136 137 void clear(int count, TRAPS); 138 void trigger(int count, TRAPS); 139 public: 140 SensorInfo(); 141 void set_sensor(instanceOop sensor) { 142 assert(_sensor_obj == NULL, "Should be set only once"); 143 _sensor_obj = sensor; 144 } 145 146 bool has_pending_requests() { 147 return (_pending_trigger_count > 0 || _pending_clear_count > 0); 148 } 149 150 int pending_trigger_count() { return _pending_trigger_count; } 151 int pending_clear_count() { return _pending_clear_count; } 152 153 // When this method is used, the memory usage is monitored 154 // as a gauge attribute. High and low thresholds are designed 155 // to provide a hysteresis mechanism to avoid repeated triggering 156 // of notifications when the attribute value makes small oscillations 157 // around the high or low threshold value. 158 // 159 // The sensor will be triggered if: 160 // (1) the usage is crossing above the high threshold and 161 // the sensor is currently off and no pending 162 // trigger requests; or 163 // (2) the usage is crossing above the high threshold and 164 // the sensor will be off (i.e. sensor is currently on 165 // and has pending clear requests). 166 // 167 // Subsequent crossings of the high threshold value do not cause 168 // any triggers unless the usage becomes less than the low threshold. 169 // 170 // The sensor will be cleared if: 171 // (1) the usage is crossing below the low threshold and 172 // the sensor is currently on and no pending 173 // clear requests; or 174 // (2) the usage is crossing below the low threshold and 175 // the sensor will be on (i.e. sensor is currently off 176 // and has pending trigger requests). 177 // 178 // Subsequent crossings of the low threshold value do not cause 179 // any clears unless the usage becomes greater than or equal 180 // to the high threshold. 181 // 182 // If the current level is between high and low threhsold, no change. 183 // 184 void set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* high_low_threshold); 185 186 // When this method is used, the memory usage is monitored as a 187 // simple counter attribute. The sensor will be triggered 188 // whenever the usage is crossing the threshold to keep track 189 // of the number of times the VM detects such a condition occurs. 190 // 191 // The sensor will be triggered if: 192 // - the usage is crossing above the high threshold regardless 193 // of the current sensor state. 194 // 195 // The sensor will be cleared if: 196 // (1) the usage is crossing below the low threshold and 197 // the sensor is currently on; or 198 // (2) the usage is crossing below the low threshold and 199 // the sensor will be on (i.e. sensor is currently off 200 // and has pending trigger requests). 201 // 202 void set_counter_sensor_level(MemoryUsage usage, ThresholdSupport* counter_threshold); 203 204 void process_pending_requests(TRAPS); 205 void oops_do(OopClosure* f); 206 207 #ifndef PRODUCT 208 // printing on default output stream; 209 void print(); 210 #endif // PRODUCT 211 }; 212 213 class LowMemoryDetector : public AllStatic { 214 friend class LowMemoryDetectorDisabler; 215 private: 216 // true if any collected heap has low memory detection enabled 217 static volatile bool _enabled_for_collected_pools; 218 // > 0 if temporary disabed 219 static volatile jint _disabled_count; 220 221 static LowMemoryDetectorThread* _detector_thread; 222 static void low_memory_detector_thread_entry(JavaThread* thread, TRAPS); 223 static void check_memory_usage(); 224 static bool has_pending_requests(); 225 static bool temporary_disabled() { return _disabled_count > 0; } 226 static void disable() { Atomic::inc(&_disabled_count); } 227 static void enable() { Atomic::dec(&_disabled_count); } 228 229 public: 230 static void initialize(); 231 static void detect_low_memory(); 232 static void detect_low_memory(MemoryPool* pool); 233 static void detect_after_gc_memory(MemoryPool* pool); 234 235 static bool is_enabled(MemoryPool* pool) { 236 // low memory detection is enabled for collected memory pools 237 // iff one of the collected memory pool has a sensor and the 238 // threshold set non-zero 239 if (pool->usage_sensor() == NULL) { 240 return false; 241 } else { 242 ThresholdSupport* threshold_support = pool->usage_threshold(); 243 return (threshold_support->is_high_threshold_supported() ? 244 (threshold_support->high_threshold() > 0) : false); 245 } 246 } 247 248 // indicates if low memory detection is enabled for any collected 249 // memory pools 250 static inline bool is_enabled_for_collected_pools() { 251 return !temporary_disabled() && _enabled_for_collected_pools; 252 } 253 254 // recompute enabled flag 255 static void recompute_enabled_for_collected_pools(); 256 257 // low memory detection for collected memory pools. 258 static inline void detect_low_memory_for_collected_pools() { 259 // no-op if low memory detection not enabled 260 if (!is_enabled_for_collected_pools()) { 261 return; 262 } 263 int num_memory_pools = MemoryService::num_memory_pools(); 264 for (int i=0; i<num_memory_pools; i++) { 265 MemoryPool* pool = MemoryService::get_memory_pool(i); 266 267 // if low memory detection is enabled then check if the 268 // current used exceeds the high threshold 269 if (pool->is_collected_pool() && is_enabled(pool)) { 270 size_t used = pool->used_in_bytes(); 271 size_t high = pool->usage_threshold()->high_threshold(); 272 if (used > high) { 273 detect_low_memory(pool); 274 } 275 } 276 } 277 } 278 279 }; 280 281 class LowMemoryDetectorDisabler: public StackObj { 282 public: 283 LowMemoryDetectorDisabler() 284 { 285 LowMemoryDetector::disable(); 286 } 287 ~LowMemoryDetectorDisabler() 288 { 289 assert(LowMemoryDetector::temporary_disabled(), "should be disabled!"); 290 LowMemoryDetector::enable(); 291 } 292 }; 293 294 #endif // SHARE_VM_SERVICES_LOWMEMORYDETECTOR_HPP