1 /*
2 * Copyright (c) 2003, 2020, 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 #include "precompiled.hpp"
26 #include "classfile/systemDictionary.hpp"
27 #include "classfile/vmSymbols.hpp"
28 #include "memory/resourceArea.hpp"
29 #include "memory/universe.hpp"
30 #include "oops/oop.inline.hpp"
31 #include "oops/oopHandle.inline.hpp"
32 #include "runtime/handles.inline.hpp"
33 #include "runtime/interfaceSupport.inline.hpp"
34 #include "runtime/java.hpp"
35 #include "runtime/javaCalls.hpp"
36 #include "runtime/mutex.hpp"
37 #include "runtime/mutexLocker.hpp"
38 #include "services/lowMemoryDetector.hpp"
39 #include "services/management.hpp"
40
41 volatile bool LowMemoryDetector::_enabled_for_collected_pools = false;
42 volatile jint LowMemoryDetector::_disabled_count = 0;
43
has_pending_requests()44 bool LowMemoryDetector::has_pending_requests() {
45 assert(Notification_lock->owned_by_self(), "Must own Notification_lock");
46 bool has_requests = false;
47 int num_memory_pools = MemoryService::num_memory_pools();
48 for (int i = 0; i < num_memory_pools; i++) {
49 MemoryPool* pool = MemoryService::get_memory_pool(i);
50 SensorInfo* sensor = pool->usage_sensor();
51 if (sensor != NULL) {
52 has_requests = has_requests || sensor->has_pending_requests();
53 }
54
55 SensorInfo* gc_sensor = pool->gc_usage_sensor();
56 if (gc_sensor != NULL) {
57 has_requests = has_requests || gc_sensor->has_pending_requests();
58 }
59 }
60 return has_requests;
61 }
62
process_sensor_changes(TRAPS)63 void LowMemoryDetector::process_sensor_changes(TRAPS) {
64 ResourceMark rm(THREAD);
65 HandleMark hm(THREAD);
66
67 // No need to hold Notification_lock to call out to Java
68 int num_memory_pools = MemoryService::num_memory_pools();
69 for (int i = 0; i < num_memory_pools; i++) {
70 MemoryPool* pool = MemoryService::get_memory_pool(i);
71 SensorInfo* sensor = pool->usage_sensor();
72 SensorInfo* gc_sensor = pool->gc_usage_sensor();
73 if (sensor != NULL && sensor->has_pending_requests()) {
74 sensor->process_pending_requests(CHECK);
75 }
76 if (gc_sensor != NULL && gc_sensor->has_pending_requests()) {
77 gc_sensor->process_pending_requests(CHECK);
78 }
79 }
80 }
81
82 // This method could be called from any Java threads
83 // and also VMThread.
detect_low_memory()84 void LowMemoryDetector::detect_low_memory() {
85 MutexLocker ml(Notification_lock, Mutex::_no_safepoint_check_flag);
86
87 bool has_pending_requests = false;
88 int num_memory_pools = MemoryService::num_memory_pools();
89 for (int i = 0; i < num_memory_pools; i++) {
90 MemoryPool* pool = MemoryService::get_memory_pool(i);
91 SensorInfo* sensor = pool->usage_sensor();
92 if (sensor != NULL &&
93 pool->usage_threshold()->is_high_threshold_supported() &&
94 pool->usage_threshold()->high_threshold() != 0) {
95 MemoryUsage usage = pool->get_memory_usage();
96 sensor->set_gauge_sensor_level(usage,
97 pool->usage_threshold());
98 has_pending_requests = has_pending_requests || sensor->has_pending_requests();
99 }
100 }
101
102 if (has_pending_requests) {
103 Notification_lock->notify_all();
104 }
105 }
106
107 // This method could be called from any Java threads
108 // and also VMThread.
detect_low_memory(MemoryPool * pool)109 void LowMemoryDetector::detect_low_memory(MemoryPool* pool) {
110 SensorInfo* sensor = pool->usage_sensor();
111 if (sensor == NULL ||
112 !pool->usage_threshold()->is_high_threshold_supported() ||
113 pool->usage_threshold()->high_threshold() == 0) {
114 return;
115 }
116
117 {
118 MutexLocker ml(Notification_lock, Mutex::_no_safepoint_check_flag);
119
120 MemoryUsage usage = pool->get_memory_usage();
121 sensor->set_gauge_sensor_level(usage,
122 pool->usage_threshold());
123 if (sensor->has_pending_requests()) {
124 // notify sensor state update
125 Notification_lock->notify_all();
126 }
127 }
128 }
129
130 // Only called by VMThread at GC time
detect_after_gc_memory(MemoryPool * pool)131 void LowMemoryDetector::detect_after_gc_memory(MemoryPool* pool) {
132 SensorInfo* sensor = pool->gc_usage_sensor();
133 if (sensor == NULL ||
134 !pool->gc_usage_threshold()->is_high_threshold_supported() ||
135 pool->gc_usage_threshold()->high_threshold() == 0) {
136 return;
137 }
138
139 {
140 MutexLocker ml(Notification_lock, Mutex::_no_safepoint_check_flag);
141
142 MemoryUsage usage = pool->get_last_collection_usage();
143 sensor->set_counter_sensor_level(usage, pool->gc_usage_threshold());
144
145 if (sensor->has_pending_requests()) {
146 // notify sensor state update
147 Notification_lock->notify_all();
148 }
149 }
150 }
151
152 // recompute enabled flag
recompute_enabled_for_collected_pools()153 void LowMemoryDetector::recompute_enabled_for_collected_pools() {
154 bool enabled = false;
155 int num_memory_pools = MemoryService::num_memory_pools();
156 for (int i=0; i<num_memory_pools; i++) {
157 MemoryPool* pool = MemoryService::get_memory_pool(i);
158 if (pool->is_collected_pool() && is_enabled(pool)) {
159 enabled = true;
160 break;
161 }
162 }
163 _enabled_for_collected_pools = enabled;
164 }
165
SensorInfo()166 SensorInfo::SensorInfo() {
167 _sensor_on = false;
168 _sensor_count = 0;
169 _pending_trigger_count = 0;
170 _pending_clear_count = 0;
171 }
172
set_sensor(instanceOop sensor)173 void SensorInfo::set_sensor(instanceOop sensor) {
174 assert(_sensor_obj.peek() == NULL, "Should be set only once");
175 _sensor_obj = OopHandle(Universe::vm_global(), sensor);
176 }
177
178
179 // When this method is used, the memory usage is monitored
180 // as a gauge attribute. Sensor notifications (trigger or
181 // clear) is only emitted at the first time it crosses
182 // a threshold.
183 //
184 // High and low thresholds are designed to provide a
185 // hysteresis mechanism to avoid repeated triggering
186 // of notifications when the attribute value makes small oscillations
187 // around the high or low threshold value.
188 //
189 // The sensor will be triggered if:
190 // (1) the usage is crossing above the high threshold and
191 // the sensor is currently off and no pending
192 // trigger requests; or
193 // (2) the usage is crossing above the high threshold and
194 // the sensor will be off (i.e. sensor is currently on
195 // and has pending clear requests).
196 //
197 // Subsequent crossings of the high threshold value do not cause
198 // any triggers unless the usage becomes less than the low threshold.
199 //
200 // The sensor will be cleared if:
201 // (1) the usage is crossing below the low threshold and
202 // the sensor is currently on and no pending
203 // clear requests; or
204 // (2) the usage is crossing below the low threshold and
205 // the sensor will be on (i.e. sensor is currently off
206 // and has pending trigger requests).
207 //
208 // Subsequent crossings of the low threshold value do not cause
209 // any clears unless the usage becomes greater than or equal
210 // to the high threshold.
211 //
212 // If the current level is between high and low threshold, no change.
213 //
set_gauge_sensor_level(MemoryUsage usage,ThresholdSupport * high_low_threshold)214 void SensorInfo::set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* high_low_threshold) {
215 assert(Notification_lock->owned_by_self(), "Must own Notification_lock");
216 assert(high_low_threshold->is_high_threshold_supported(), "just checking");
217
218 bool is_over_high = high_low_threshold->is_high_threshold_crossed(usage);
219 bool is_below_low = high_low_threshold->is_low_threshold_crossed(usage);
220
221 assert(!(is_over_high && is_below_low), "Can't be both true");
222
223 if (is_over_high &&
224 ((!_sensor_on && _pending_trigger_count == 0) ||
225 _pending_clear_count > 0)) {
226 // low memory detected and need to increment the trigger pending count
227 // if the sensor is off or will be off due to _pending_clear_ > 0
228 // Request to trigger the sensor
229 _pending_trigger_count++;
230 _usage = usage;
231
232 if (_pending_clear_count > 0) {
233 // non-zero pending clear requests indicates that there are
234 // pending requests to clear this sensor.
235 // This trigger request needs to clear this clear count
236 // since the resulting sensor flag should be on.
237 _pending_clear_count = 0;
238 }
239 } else if (is_below_low &&
240 ((_sensor_on && _pending_clear_count == 0) ||
241 (_pending_trigger_count > 0 && _pending_clear_count == 0))) {
242 // memory usage returns below the threshold
243 // Request to clear the sensor if the sensor is on or will be on due to
244 // _pending_trigger_count > 0 and also no clear request
245 _pending_clear_count++;
246 }
247 }
248
249 // When this method is used, the memory usage is monitored as a
250 // simple counter attribute. The sensor will be triggered
251 // whenever the usage is crossing the threshold to keep track
252 // of the number of times the VM detects such a condition occurs.
253 //
254 // High and low thresholds are designed to provide a
255 // hysteresis mechanism to avoid repeated triggering
256 // of notifications when the attribute value makes small oscillations
257 // around the high or low threshold value.
258 //
259 // The sensor will be triggered if:
260 // - the usage is crossing above the high threshold regardless
261 // of the current sensor state.
262 //
263 // The sensor will be cleared if:
264 // (1) the usage is crossing below the low threshold and
265 // the sensor is currently on; or
266 // (2) the usage is crossing below the low threshold and
267 // the sensor will be on (i.e. sensor is currently off
268 // and has pending trigger requests).
set_counter_sensor_level(MemoryUsage usage,ThresholdSupport * counter_threshold)269 void SensorInfo::set_counter_sensor_level(MemoryUsage usage, ThresholdSupport* counter_threshold) {
270 assert(Notification_lock->owned_by_self(), "Must own Notification_lock");
271 assert(counter_threshold->is_high_threshold_supported(), "just checking");
272
273 bool is_over_high = counter_threshold->is_high_threshold_crossed(usage);
274 bool is_below_low = counter_threshold->is_low_threshold_crossed(usage);
275
276 assert(!(is_over_high && is_below_low), "Can't be both true");
277
278 if (is_over_high) {
279 _pending_trigger_count++;
280 _usage = usage;
281 _pending_clear_count = 0;
282 } else if (is_below_low && (_sensor_on || _pending_trigger_count > 0)) {
283 _pending_clear_count++;
284 }
285 }
286
process_pending_requests(TRAPS)287 void SensorInfo::process_pending_requests(TRAPS) {
288 int pending_count = pending_trigger_count();
289 if (pending_clear_count() > 0) {
290 clear(pending_count, CHECK);
291 } else {
292 trigger(pending_count, CHECK);
293 }
294
295 }
296
trigger(int count,TRAPS)297 void SensorInfo::trigger(int count, TRAPS) {
298 assert(count <= _pending_trigger_count, "just checking");
299 Handle sensor_h(THREAD, _sensor_obj.resolve());
300 if (sensor_h() != NULL) {
301 InstanceKlass* sensorKlass = Management::sun_management_Sensor_klass(CHECK);
302 Symbol* trigger_method_signature;
303
304 JavaValue result(T_VOID);
305 JavaCallArguments args(sensor_h);
306 args.push_int((int) count);
307
308 Handle usage_h = MemoryService::create_MemoryUsage_obj(_usage, THREAD);
309 // Call Sensor::trigger(int, MemoryUsage) to send notification to listeners.
310 // When OOME occurs and fails to allocate MemoryUsage object, call
311 // Sensor::trigger(int) instead. The pending request will be processed
312 // but no notification will be sent.
313 if (HAS_PENDING_EXCEPTION) {
314 assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOME here");
315 CLEAR_PENDING_EXCEPTION;
316 trigger_method_signature = vmSymbols::int_void_signature();
317 } else {
318 trigger_method_signature = vmSymbols::trigger_method_signature();
319 args.push_oop(usage_h);
320 }
321
322 JavaCalls::call_virtual(&result,
323 sensorKlass,
324 vmSymbols::trigger_name(),
325 trigger_method_signature,
326 &args,
327 THREAD);
328
329 if (HAS_PENDING_EXCEPTION) {
330 // We just clear the OOM pending exception that we might have encountered
331 // in Java's tiggerAction(), and continue with updating the counters since
332 // the Java counters have been updated too.
333 assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOME here");
334 CLEAR_PENDING_EXCEPTION;
335 }
336 }
337
338 {
339 // Holds Notification_lock and update the sensor state
340 MutexLocker ml(THREAD, Notification_lock, Mutex::_no_safepoint_check_flag);
341 assert(_pending_trigger_count > 0, "Must have pending trigger");
342 _sensor_on = true;
343 _sensor_count += count;
344 _pending_trigger_count = _pending_trigger_count - count;
345 }
346 }
347
clear(int count,TRAPS)348 void SensorInfo::clear(int count, TRAPS) {
349 {
350 // Holds Notification_lock and update the sensor state
351 MutexLocker ml(THREAD, Notification_lock, Mutex::_no_safepoint_check_flag);
352 if (_pending_clear_count == 0) {
353 // Bail out if we lost a race to set_*_sensor_level() which may have
354 // reactivated the sensor in the meantime because it was triggered again.
355 return;
356 }
357 _sensor_on = false;
358 _sensor_count += count;
359 _pending_clear_count = 0;
360 _pending_trigger_count = _pending_trigger_count - count;
361 }
362
363 Handle sensor(THREAD, _sensor_obj.resolve());
364 if (sensor() != NULL) {
365 InstanceKlass* sensorKlass = Management::sun_management_Sensor_klass(CHECK);
366 JavaValue result(T_VOID);
367 JavaCallArguments args(sensor);
368 args.push_int((int) count);
369 JavaCalls::call_virtual(&result,
370 sensorKlass,
371 vmSymbols::clear_name(),
372 vmSymbols::int_void_signature(),
373 &args,
374 CHECK);
375 }
376 }
377
378 //--------------------------------------------------------------
379 // Non-product code
380
381 #ifndef PRODUCT
print()382 void SensorInfo::print() {
383 tty->print_cr("%s count = " SIZE_FORMAT " pending_triggers = %d pending_clears = %d",
384 (_sensor_on ? "on" : "off"),
385 _sensor_count, _pending_trigger_count, _pending_clear_count);
386 }
387
388 #endif // PRODUCT
389