lowMemoryDetector.hpp revision 3718:b9a9ed0f8eeb
1/*
2 * Copyright (c) 2003, 2012, 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// Memory detection code runs in the Service thread (serviceThread.hpp).
62
63class OopClosure;
64class MemoryPool;
65
66class ThresholdSupport : public CHeapObj<mtInternal> {
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
115class SensorInfo : public CHeapObj<mtInternal> {
116private:
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);
139public:
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
213class LowMemoryDetector : public AllStatic {
214  friend class LowMemoryDetectorDisabler;
215  friend class ServiceThread;
216private:
217  // true if any collected heap has low memory detection enabled
218  static volatile bool _enabled_for_collected_pools;
219  // > 0 if temporary disabed
220  static volatile jint _disabled_count;
221
222  static void check_memory_usage();
223  static bool has_pending_requests();
224  static bool temporary_disabled() { return _disabled_count > 0; }
225  static void disable() { Atomic::inc(&_disabled_count); }
226  static void enable() { Atomic::dec(&_disabled_count); }
227  static void process_sensor_changes(TRAPS);
228
229public:
230  static void detect_low_memory();
231  static void detect_low_memory(MemoryPool* pool);
232  static void detect_after_gc_memory(MemoryPool* pool);
233
234  static bool is_enabled(MemoryPool* pool) {
235    // low memory detection is enabled for collected memory pools
236    // iff one of the collected memory pool has a sensor and the
237    // threshold set non-zero
238    if (pool->usage_sensor() == NULL) {
239      return false;
240    } else {
241      ThresholdSupport* threshold_support = pool->usage_threshold();
242      return (threshold_support->is_high_threshold_supported() ?
243               (threshold_support->high_threshold() > 0) : false);
244    }
245  }
246
247  // indicates if low memory detection is enabled for any collected
248  // memory pools
249  static inline bool is_enabled_for_collected_pools() {
250    return !temporary_disabled() && _enabled_for_collected_pools;
251  }
252
253  // recompute enabled flag
254  static void recompute_enabled_for_collected_pools();
255
256  // low memory detection for collected memory pools.
257  static inline void detect_low_memory_for_collected_pools() {
258    // no-op if low memory detection not enabled
259    if (!is_enabled_for_collected_pools()) {
260      return;
261    }
262    int num_memory_pools = MemoryService::num_memory_pools();
263    for (int i=0; i<num_memory_pools; i++) {
264      MemoryPool* pool = MemoryService::get_memory_pool(i);
265
266      // if low memory detection is enabled then check if the
267      // current used exceeds the high threshold
268      if (pool->is_collected_pool() && is_enabled(pool)) {
269        size_t used = pool->used_in_bytes();
270        size_t high = pool->usage_threshold()->high_threshold();
271        if (used > high) {
272          detect_low_memory(pool);
273        }
274      }
275    }
276  }
277};
278
279class LowMemoryDetectorDisabler: public StackObj {
280public:
281  LowMemoryDetectorDisabler()
282  {
283    LowMemoryDetector::disable();
284  }
285  ~LowMemoryDetectorDisabler()
286  {
287    assert(LowMemoryDetector::temporary_disabled(), "should be disabled!");
288    LowMemoryDetector::enable();
289  }
290};
291
292#endif // SHARE_VM_SERVICES_LOWMEMORYDETECTOR_HPP
293