Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/services/lowMemoryDetector.hpp
32285 views
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
63
class OopClosure;
64
class MemoryPool;
65
66
class 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
115
class SensorInfo : public CHeapObj<mtInternal> {
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
friend class ServiceThread;
216
private:
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
229
public:
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
279
class LowMemoryDetectorDisabler: public StackObj {
280
public:
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
294