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