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