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