Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/services/lowMemoryDetector.cpp
32285 views
/*1* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "classfile/systemDictionary.hpp"26#include "classfile/vmSymbols.hpp"27#include "oops/oop.inline.hpp"28#include "runtime/interfaceSupport.hpp"29#include "runtime/java.hpp"30#include "runtime/javaCalls.hpp"31#include "runtime/mutex.hpp"32#include "runtime/mutexLocker.hpp"33#include "services/lowMemoryDetector.hpp"34#include "services/management.hpp"3536volatile bool LowMemoryDetector::_enabled_for_collected_pools = false;37volatile jint LowMemoryDetector::_disabled_count = 0;3839bool LowMemoryDetector::has_pending_requests() {40assert(Service_lock->owned_by_self(), "Must own Service_lock");41bool has_requests = false;42int num_memory_pools = MemoryService::num_memory_pools();43for (int i = 0; i < num_memory_pools; i++) {44MemoryPool* pool = MemoryService::get_memory_pool(i);45SensorInfo* sensor = pool->usage_sensor();46if (sensor != NULL) {47has_requests = has_requests || sensor->has_pending_requests();48}4950SensorInfo* gc_sensor = pool->gc_usage_sensor();51if (gc_sensor != NULL) {52has_requests = has_requests || gc_sensor->has_pending_requests();53}54}55return has_requests;56}5758void LowMemoryDetector::process_sensor_changes(TRAPS) {59ResourceMark rm(THREAD);60HandleMark hm(THREAD);6162// No need to hold Service_lock to call out to Java63int num_memory_pools = MemoryService::num_memory_pools();64for (int i = 0; i < num_memory_pools; i++) {65MemoryPool* pool = MemoryService::get_memory_pool(i);66SensorInfo* sensor = pool->usage_sensor();67SensorInfo* gc_sensor = pool->gc_usage_sensor();68if (sensor != NULL && sensor->has_pending_requests()) {69sensor->process_pending_requests(CHECK);70}71if (gc_sensor != NULL && gc_sensor->has_pending_requests()) {72gc_sensor->process_pending_requests(CHECK);73}74}75}7677// This method could be called from any Java threads78// and also VMThread.79void LowMemoryDetector::detect_low_memory() {80MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);8182bool has_pending_requests = false;83int num_memory_pools = MemoryService::num_memory_pools();84for (int i = 0; i < num_memory_pools; i++) {85MemoryPool* pool = MemoryService::get_memory_pool(i);86SensorInfo* sensor = pool->usage_sensor();87if (sensor != NULL &&88pool->usage_threshold()->is_high_threshold_supported() &&89pool->usage_threshold()->high_threshold() != 0) {90MemoryUsage usage = pool->get_memory_usage();91sensor->set_gauge_sensor_level(usage,92pool->usage_threshold());93has_pending_requests = has_pending_requests || sensor->has_pending_requests();94}95}9697if (has_pending_requests) {98Service_lock->notify_all();99}100}101102// This method could be called from any Java threads103// and also VMThread.104void LowMemoryDetector::detect_low_memory(MemoryPool* pool) {105SensorInfo* sensor = pool->usage_sensor();106if (sensor == NULL ||107!pool->usage_threshold()->is_high_threshold_supported() ||108pool->usage_threshold()->high_threshold() == 0) {109return;110}111112{113MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);114115MemoryUsage usage = pool->get_memory_usage();116sensor->set_gauge_sensor_level(usage,117pool->usage_threshold());118if (sensor->has_pending_requests()) {119// notify sensor state update120Service_lock->notify_all();121}122}123}124125// Only called by VMThread at GC time126void LowMemoryDetector::detect_after_gc_memory(MemoryPool* pool) {127SensorInfo* sensor = pool->gc_usage_sensor();128if (sensor == NULL ||129!pool->gc_usage_threshold()->is_high_threshold_supported() ||130pool->gc_usage_threshold()->high_threshold() == 0) {131return;132}133134{135MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);136137MemoryUsage usage = pool->get_last_collection_usage();138sensor->set_counter_sensor_level(usage, pool->gc_usage_threshold());139140if (sensor->has_pending_requests()) {141// notify sensor state update142Service_lock->notify_all();143}144}145}146147// recompute enabled flag148void LowMemoryDetector::recompute_enabled_for_collected_pools() {149bool enabled = false;150int num_memory_pools = MemoryService::num_memory_pools();151for (int i=0; i<num_memory_pools; i++) {152MemoryPool* pool = MemoryService::get_memory_pool(i);153if (pool->is_collected_pool() && is_enabled(pool)) {154enabled = true;155break;156}157}158_enabled_for_collected_pools = enabled;159}160161SensorInfo::SensorInfo() {162_sensor_obj = NULL;163_sensor_on = false;164_sensor_count = 0;165_pending_trigger_count = 0;166_pending_clear_count = 0;167}168169// When this method is used, the memory usage is monitored170// as a gauge attribute. Sensor notifications (trigger or171// clear) is only emitted at the first time it crosses172// a threshold.173//174// High and low thresholds are designed to provide a175// hysteresis mechanism to avoid repeated triggering176// of notifications when the attribute value makes small oscillations177// around the high or low threshold value.178//179// The sensor will be triggered if:180// (1) the usage is crossing above the high threshold and181// the sensor is currently off and no pending182// trigger requests; or183// (2) the usage is crossing above the high threshold and184// the sensor will be off (i.e. sensor is currently on185// and has pending clear requests).186//187// Subsequent crossings of the high threshold value do not cause188// any triggers unless the usage becomes less than the low threshold.189//190// The sensor will be cleared if:191// (1) the usage is crossing below the low threshold and192// the sensor is currently on and no pending193// clear requests; or194// (2) the usage is crossing below the low threshold and195// the sensor will be on (i.e. sensor is currently off196// and has pending trigger requests).197//198// Subsequent crossings of the low threshold value do not cause199// any clears unless the usage becomes greater than or equal200// to the high threshold.201//202// If the current level is between high and low threhsold, no change.203//204void SensorInfo::set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* high_low_threshold) {205assert(high_low_threshold->is_high_threshold_supported(), "just checking");206207bool is_over_high = high_low_threshold->is_high_threshold_crossed(usage);208bool is_below_low = high_low_threshold->is_low_threshold_crossed(usage);209210assert(!(is_over_high && is_below_low), "Can't be both true");211212if (is_over_high &&213((!_sensor_on && _pending_trigger_count == 0) ||214_pending_clear_count > 0)) {215// low memory detected and need to increment the trigger pending count216// if the sensor is off or will be off due to _pending_clear_ > 0217// Request to trigger the sensor218_pending_trigger_count++;219_usage = usage;220221if (_pending_clear_count > 0) {222// non-zero pending clear requests indicates that there are223// pending requests to clear this sensor.224// This trigger request needs to clear this clear count225// since the resulting sensor flag should be on.226_pending_clear_count = 0;227}228} else if (is_below_low &&229((_sensor_on && _pending_clear_count == 0) ||230(_pending_trigger_count > 0 && _pending_clear_count == 0))) {231// memory usage returns below the threshold232// Request to clear the sensor if the sensor is on or will be on due to233// _pending_trigger_count > 0 and also no clear request234_pending_clear_count++;235}236}237238// When this method is used, the memory usage is monitored as a239// simple counter attribute. The sensor will be triggered240// whenever the usage is crossing the threshold to keep track241// of the number of times the VM detects such a condition occurs.242//243// High and low thresholds are designed to provide a244// hysteresis mechanism to avoid repeated triggering245// of notifications when the attribute value makes small oscillations246// around the high or low threshold value.247//248// The sensor will be triggered if:249// - the usage is crossing above the high threshold regardless250// of the current sensor state.251//252// The sensor will be cleared if:253// (1) the usage is crossing below the low threshold and254// the sensor is currently on; or255// (2) the usage is crossing below the low threshold and256// the sensor will be on (i.e. sensor is currently off257// and has pending trigger requests).258void SensorInfo::set_counter_sensor_level(MemoryUsage usage, ThresholdSupport* counter_threshold) {259assert(counter_threshold->is_high_threshold_supported(), "just checking");260261bool is_over_high = counter_threshold->is_high_threshold_crossed(usage);262bool is_below_low = counter_threshold->is_low_threshold_crossed(usage);263264assert(!(is_over_high && is_below_low), "Can't be both true");265266if (is_over_high) {267_pending_trigger_count++;268_usage = usage;269_pending_clear_count = 0;270} else if (is_below_low && (_sensor_on || _pending_trigger_count > 0)) {271_pending_clear_count++;272}273}274275void SensorInfo::oops_do(OopClosure* f) {276f->do_oop((oop*) &_sensor_obj);277}278279void SensorInfo::process_pending_requests(TRAPS) {280if (!has_pending_requests()) {281return;282}283284int pending_count = pending_trigger_count();285if (pending_clear_count() > 0) {286clear(pending_count, CHECK);287} else {288trigger(pending_count, CHECK);289}290291}292293void SensorInfo::trigger(int count, TRAPS) {294assert(count <= _pending_trigger_count, "just checking");295296if (_sensor_obj != NULL) {297Klass* k = Management::sun_management_Sensor_klass(CHECK);298instanceKlassHandle sensorKlass (THREAD, k);299Handle sensor_h(THREAD, _sensor_obj);300301Symbol* trigger_method_signature;302303JavaValue result(T_VOID);304JavaCallArguments args(sensor_h);305args.push_int((int) count);306307Handle usage_h = MemoryService::create_MemoryUsage_obj(_usage, THREAD);308// Call Sensor::trigger(int, MemoryUsage) to send notification to listeners.309// When OOME occurs and fails to allocate MemoryUsage object, call310// Sensor::trigger(int) instead. The pending request will be processed311// but no notification will be sent.312if (HAS_PENDING_EXCEPTION) {313assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOME here");314CLEAR_PENDING_EXCEPTION;315trigger_method_signature = vmSymbols::int_void_signature();316} else {317trigger_method_signature = vmSymbols::trigger_method_signature();318args.push_oop(usage_h);319}320321JavaCalls::call_virtual(&result,322sensorKlass,323vmSymbols::trigger_name(),324trigger_method_signature,325&args,326THREAD);327328if (HAS_PENDING_EXCEPTION) {329// We just clear the OOM pending exception that we might have encountered330// in Java's tiggerAction(), and continue with updating the counters since331// the Java counters have been updated too.332assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOME here");333CLEAR_PENDING_EXCEPTION;334}335}336337{338// Holds Service_lock and update the sensor state339MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);340_sensor_on = true;341_sensor_count += count;342_pending_trigger_count = _pending_trigger_count - count;343}344}345346void SensorInfo::clear(int count, TRAPS) {347if (_sensor_obj != NULL) {348Klass* k = Management::sun_management_Sensor_klass(CHECK);349instanceKlassHandle sensorKlass (THREAD, k);350Handle sensor(THREAD, _sensor_obj);351352JavaValue result(T_VOID);353JavaCallArguments args(sensor);354args.push_int((int) count);355JavaCalls::call_virtual(&result,356sensorKlass,357vmSymbols::clear_name(),358vmSymbols::int_void_signature(),359&args,360CHECK);361}362363{364// Holds Service_lock and update the sensor state365MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);366_sensor_on = false;367_pending_clear_count = 0;368_pending_trigger_count = _pending_trigger_count - count;369}370}371372//--------------------------------------------------------------373// Non-product code374375#ifndef PRODUCT376void SensorInfo::print() {377tty->print_cr("%s count = " SIZE_FORMAT " pending_triggers = %d pending_clears = %d",378(_sensor_on ? "on" : "off"),379_sensor_count, _pending_trigger_count, _pending_clear_count);380}381382#endif // PRODUCT383384385