Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/services/lowMemoryDetector.hpp
32285 views
/*1* Copyright (c) 2003, 2012, 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#ifndef SHARE_VM_SERVICES_LOWMEMORYDETECTOR_HPP25#define SHARE_VM_SERVICES_LOWMEMORYDETECTOR_HPP2627#include "memory/allocation.hpp"28#include "services/memoryPool.hpp"29#include "services/memoryService.hpp"3031// Low Memory Detection Support32// Two memory alarms in the JDK (we called them sensors).33// - Heap memory sensor34// - Non-heap memory sensor35// When the VM detects if the memory usage of a memory pool has reached36// or exceeded its threshold, it will trigger the sensor for the type37// of the memory pool (heap or nonheap or both).38//39// If threshold == -1, no low memory detection is supported and40// the threshold value is not allowed to be changed.41// If threshold == 0, no low memory detection is performed for42// that memory pool. The threshold can be set to any non-negative43// value.44//45// The default threshold of the Hotspot memory pools are:46// Eden space -147// Survivor space 1 -148// Survivor space 2 -149// Old generation 050// Perm generation 051// CodeCache 052//53// For heap memory, detection will be performed when GC finishes54// and also in the slow path allocation.55// For Code cache, detection will be performed in the allocation56// and deallocation.57//58// May need to deal with hysteresis effect.59//60// Memory detection code runs in the Service thread (serviceThread.hpp).6162class OopClosure;63class MemoryPool;6465class ThresholdSupport : public CHeapObj<mtInternal> {66private:67bool _support_high_threshold;68bool _support_low_threshold;69size_t _high_threshold;70size_t _low_threshold;71public:72ThresholdSupport(bool support_high, bool support_low) {73_support_high_threshold = support_high;74_support_low_threshold = support_low;75_high_threshold = 0;76_low_threshold= 0;77}7879size_t high_threshold() const { return _high_threshold; }80size_t low_threshold() const { return _low_threshold; }81bool is_high_threshold_supported() { return _support_high_threshold; }82bool is_low_threshold_supported() { return _support_low_threshold; }8384bool is_high_threshold_crossed(MemoryUsage usage) {85if (_support_high_threshold && _high_threshold > 0) {86return (usage.used() >= _high_threshold);87}88return false;89}90bool is_low_threshold_crossed(MemoryUsage usage) {91if (_support_low_threshold && _low_threshold > 0) {92return (usage.used() < _low_threshold);93}94return false;95}9697size_t set_high_threshold(size_t new_threshold) {98assert(_support_high_threshold, "can only be set if supported");99assert(new_threshold >= _low_threshold, "new_threshold must be >= _low_threshold");100size_t prev = _high_threshold;101_high_threshold = new_threshold;102return prev;103}104105size_t set_low_threshold(size_t new_threshold) {106assert(_support_low_threshold, "can only be set if supported");107assert(new_threshold <= _high_threshold, "new_threshold must be <= _high_threshold");108size_t prev = _low_threshold;109_low_threshold = new_threshold;110return prev;111}112};113114class SensorInfo : public CHeapObj<mtInternal> {115private:116instanceOop _sensor_obj;117bool _sensor_on;118size_t _sensor_count;119120// before the actual sensor on flag and sensor count are set121// we maintain the number of pending triggers and clears.122// _pending_trigger_count means the number of pending triggers123// and the sensor count should be incremented by the same number.124125int _pending_trigger_count;126127// _pending_clear_count takes precedence if it's > 0 which128// indicates the resulting sensor will be off129// Sensor trigger requests will reset this clear count to130// indicate the resulting flag should be on.131132int _pending_clear_count;133134MemoryUsage _usage;135136void clear(int count, TRAPS);137void trigger(int count, TRAPS);138public:139SensorInfo();140void set_sensor(instanceOop sensor) {141assert(_sensor_obj == NULL, "Should be set only once");142_sensor_obj = sensor;143}144145bool has_pending_requests() {146return (_pending_trigger_count > 0 || _pending_clear_count > 0);147}148149int pending_trigger_count() { return _pending_trigger_count; }150int pending_clear_count() { return _pending_clear_count; }151152// When this method is used, the memory usage is monitored153// as a gauge attribute. High and low thresholds are designed154// to provide a hysteresis mechanism to avoid repeated triggering155// of notifications when the attribute value makes small oscillations156// around the high or low threshold value.157//158// The sensor will be triggered if:159// (1) the usage is crossing above the high threshold and160// the sensor is currently off and no pending161// trigger requests; or162// (2) the usage is crossing above the high threshold and163// the sensor will be off (i.e. sensor is currently on164// and has pending clear requests).165//166// Subsequent crossings of the high threshold value do not cause167// any triggers unless the usage becomes less than the low threshold.168//169// The sensor will be cleared if:170// (1) the usage is crossing below the low threshold and171// the sensor is currently on and no pending172// clear requests; or173// (2) the usage is crossing below the low threshold and174// the sensor will be on (i.e. sensor is currently off175// and has pending trigger requests).176//177// Subsequent crossings of the low threshold value do not cause178// any clears unless the usage becomes greater than or equal179// to the high threshold.180//181// If the current level is between high and low threhsold, no change.182//183void set_gauge_sensor_level(MemoryUsage usage, ThresholdSupport* high_low_threshold);184185// When this method is used, the memory usage is monitored as a186// simple counter attribute. The sensor will be triggered187// whenever the usage is crossing the threshold to keep track188// of the number of times the VM detects such a condition occurs.189//190// The sensor will be triggered if:191// - the usage is crossing above the high threshold regardless192// of the current sensor state.193//194// The sensor will be cleared if:195// (1) the usage is crossing below the low threshold and196// the sensor is currently on; or197// (2) the usage is crossing below the low threshold and198// the sensor will be on (i.e. sensor is currently off199// and has pending trigger requests).200//201void set_counter_sensor_level(MemoryUsage usage, ThresholdSupport* counter_threshold);202203void process_pending_requests(TRAPS);204void oops_do(OopClosure* f);205206#ifndef PRODUCT207// printing on default output stream;208void print();209#endif // PRODUCT210};211212class LowMemoryDetector : public AllStatic {213friend class LowMemoryDetectorDisabler;214friend class ServiceThread;215private:216// true if any collected heap has low memory detection enabled217static volatile bool _enabled_for_collected_pools;218// > 0 if temporary disabed219static volatile jint _disabled_count;220221static void check_memory_usage();222static bool has_pending_requests();223static bool temporary_disabled() { return _disabled_count > 0; }224static void disable() { Atomic::inc(&_disabled_count); }225static void enable() { Atomic::dec(&_disabled_count); }226static void process_sensor_changes(TRAPS);227228public:229static void detect_low_memory();230static void detect_low_memory(MemoryPool* pool);231static void detect_after_gc_memory(MemoryPool* pool);232233static bool is_enabled(MemoryPool* pool) {234// low memory detection is enabled for collected memory pools235// iff one of the collected memory pool has a sensor and the236// threshold set non-zero237if (pool->usage_sensor() == NULL) {238return false;239} else {240ThresholdSupport* threshold_support = pool->usage_threshold();241return (threshold_support->is_high_threshold_supported() ?242(threshold_support->high_threshold() > 0) : false);243}244}245246// indicates if low memory detection is enabled for any collected247// memory pools248static inline bool is_enabled_for_collected_pools() {249return !temporary_disabled() && _enabled_for_collected_pools;250}251252// recompute enabled flag253static void recompute_enabled_for_collected_pools();254255// low memory detection for collected memory pools.256static inline void detect_low_memory_for_collected_pools() {257// no-op if low memory detection not enabled258if (!is_enabled_for_collected_pools()) {259return;260}261int num_memory_pools = MemoryService::num_memory_pools();262for (int i=0; i<num_memory_pools; i++) {263MemoryPool* pool = MemoryService::get_memory_pool(i);264265// if low memory detection is enabled then check if the266// current used exceeds the high threshold267if (pool->is_collected_pool() && is_enabled(pool)) {268size_t used = pool->used_in_bytes();269size_t high = pool->usage_threshold()->high_threshold();270if (used > high) {271detect_low_memory(pool);272}273}274}275}276};277278class LowMemoryDetectorDisabler: public StackObj {279public:280LowMemoryDetectorDisabler()281{282LowMemoryDetector::disable();283}284~LowMemoryDetectorDisabler()285{286assert(LowMemoryDetector::temporary_disabled(), "should be disabled!");287LowMemoryDetector::enable();288}289};290291#endif // SHARE_VM_SERVICES_LOWMEMORYDETECTOR_HPP292293294