Up Top

Serviceability 機能 : HotSpot Monitoring and Management Interface (JMM) : 各種 Platform MXBean クラスの処理 : メモリ使用量の閾値超過通知処理


概要(Summary)

(See: java.lang.management.MemoryPoolMXBean に関するドキュメント) (<= 特に java.lang.management.MemoryPoolMXBean.setUsageThreshold() メソッドと java.lang.management.MemoryPoolMXBean.setCollectionUsageThreshold() メソッドに関する部分)

内部的には, 閾値超過の発生の有無や発生回数を記録するために sun.management.Sensor というオブジェクトが使われている. 処理は以下のようになる.

  1. 閾値超過が起こる度に ServiceThread によって Sensor オブジェクト内の値を更新する処理が起動される.

(この際, ついでに MemoryMXBean に登録されているリスナーへの通知処理も行われる)

  1. polling 用の関数では, この Sensor オブジェクト内の値を取得するだけ.

なお, 正確に言うと sun.management.Sensor 自体は abstract クラスであり, 実際に使われるのはサブクラスである sun.management.PoolSensor と sun.management.CollectionSensor になる. それぞれの役割分担は以下の通り.

    ((cite: jdk/src/share/classes/sun/management/MemoryPoolImpl.java))
        /**
         * PoolSensor will be triggered by the VM when the memory
         * usage of a memory pool is crossing the usage threshold.
         * The VM will not trigger this sensor in subsequent crossing
         * unless the memory usage has returned below the threshold.
         */
        class PoolSensor extends Sensor {
    ((cite: jdk/src/share/classes/sun/management/MemoryPoolImpl.java))
        /**
         * CollectionSensor will be triggered and cleared by the VM
         * when the memory usage of a memory pool after GC is crossing
         * the collection threshold.
         * The VM will trigger this sensor in subsequent crossing
         * regardless if the memory usage has changed siince the previous GC.
         */
        class CollectionSensor extends Sensor {

備考(Notes)

一部の MemoryPool オブジェクトは閾値設定機能に対応していない. 対応の有無は MemoryPool オブジェクトのクラスによって決まっており, 具体的には以下の通り.

(なお, 対応有無の情報は各 MemoryPool オブジェクトの生成時に設定され, 各 MemoryPool オブジェクト内の ThresholdSupport オブジェクトに格納されている (See: MemoryPool::MemoryPool()))

collection usage threshold 機能 usage threshold 機能
CodeHeapPool 非対応(※1) 対応(※2)
CollectedMemoryPool のサブクラス どのサブクラスでも対応(※3) Old や Perm は対応. Eden や Survivor は非対応 (※4)

処理の流れ (概要)(Execution Flows : Summary)

閾値の設定処理の流れ

sun.management.MemoryPoolImpl.setUsageThreshold()
  -> sun.management.MemoryPoolImpl.setPoolUsageSensor()
     -> Java_sun_management_MemoryPoolImpl_setPoolUsageSensor()
        -> jmm_SetPoolSensor()
           -> MemoryPool::set_usage_sensor_obj()
              -> MemoryPool::set_sensor_obj_at()
  -> sun.management.MemoryPoolImpl.setUsageThreshold0()
     -> Java_sun_management_MemoryPoolImpl_setUsageThreshold0()
        -> jmm_SetPoolThreshold()
           -> LowMemoryDetector::recompute_enabled_for_collected_pools()
           -> LowMemoryDetector::detect_low_memory(MemoryPool* pool)
              -> SensorInfo::set_gauge_sensor_level()
              -> SensorInfo::has_pending_requests()
              -> Monitor::notify_all()   (<= もし送信すべき通知があれば ServiceThread を起床させる)
sun.management.MemoryPoolImpl.setCollectionUsageThreshold()
  -> sun.management.MemoryPoolImpl.setPoolCollectionSensor()
     -> Java_sun_management_MemoryPoolImpl_setPoolCollectionSensor()
        -> jmm_SetPoolSensor()
           -> MemoryPool::set_gc_usage_sensor_obj()
              -> MemoryPool::set_sensor_obj_at()
  -> sun.management.MemoryPoolImpl.setCollectionUsageThreshold0()
     -> Java_sun_management_MemoryPoolImpl_setCollectionThreshold0()
        -> jmm_SetPoolThreshold()
           -> (同上)

通知処理用のリスナー登録処理の流れ

(sun.management.MemoryImpl は sun.management.NotificationEmitterSupport のサブクラスなので, MemoryImpl オブジェクトに対して addNotificationListener() メソッドを呼び出すと sun.management.NotificationEmitterSupport.addNotificationListener() が呼び出される)

sun.management.NotificationEmitterSupport.addNotificationListener()

閾値超過時のリスナーへの通知処理の流れ

(1) ServiceThread の起床処理

(GC 終了後に TraceMemoryManagerStats のデストラクタから呼び出される)

(ここでの処理は, Java ヒープを担当する MemoryPool の gc usage threshold のチェック)

TraceMemoryManagerStats::~TraceMemoryManagerStats()
-> MemoryService::gc_end()
   -> GCMemoryManager::gc_end()
      -> LowMemoryDetector::detect_after_gc_memory()
         -> SensorInfo::set_counter_sensor_level()
         -> LowMemoryDetector::detect_low_memory(MemoryPool* pool)
            -> (同上)

(1) ServiceThread の起床処理

(メモリ確保の slow-path から呼び出される)

(ここでの処理は, Java ヒープを担当する MemoryPool の usage threshold のチェック)

post_allocation_notify()
-> LowMemoryDetector::detect_low_memory_for_collected_pools()
   -> LowMemoryDetector::is_enabled_for_collected_pools()
   -> LowMemoryDetector::detect_low_memory(MemoryPool* pool)
      -> (同上)

(1) ServiceThread の起床処理

(GC 終了後に呼び出される)

(ここでの処理は, Java ヒープを担当する MemoryPool の usage threshold のチェック)

MemoryService::track_memory_usage()
-> LowMemoryDetector::detect_low_memory()
   -> SensorInfo::set_gauge_sensor_level()
   -> SensorInfo::has_pending_requests()
   -> Monitor::notify_all()   (<= もし送信すべき通知があれば ServiceThread を起床させる)

(1) ServiceThread の起床処理

(CodeCache でのメモリの確保/解放時に呼び出される)

(ここでの処理は, CodeCache 用 MemoryPool の usage threshold のチェック)

MemoryService::track_code_cache_memory_usage()
-> MemoryService::track_memory_pool_usage()
   -> LowMemoryDetector::detect_low_memory(MemoryPool* pool)
      -> (同上)

(2) ServiceThread による通知機能の呼び出し

ServiceThread::service_thread_entry()
-> LowMemoryDetector::has_pending_requests()
-> LowMemoryDetector::process_sensor_changes()
   -> SensorInfo::process_pending_requests()
      -> SensorInfo::trigger()
         -> sun.management.Sensor.trigger()
            -> sun.management.PoolSensor.triggerAction() or sun.management.CollectionSensor.triggerAction()
               -> sun.management.MemoryImpl.createNotification()
      -> SensorInfo::clear()
         -> sun.management.Sensor.clear()
            -> sun.management.PoolSensor.clearAction() or sun.management.CollectionSensor.clearAction()

閾値超過の確認処理(polling 処理)の流れ

sun.management.MemoryPoolImpl.isUsageThresholdExceeded()
  -> sun.management.Sensor.isOn()
sun.management.MemoryPoolImpl.getUsageThresholdCount()
  -> sun.management.Sensor.getCount()
sun.management.MemoryPoolImpl.isCollectionUsageThresholdExceeded()
  -> sun.management.Sensor.isOn()
sun.management.MemoryPoolImpl.getCollectionUsageThresholdCount()
  -> sun.management.Sensor.getCount()

処理の流れ (詳細)(Execution Flows : Details)

sun.management.MemoryPoolImpl.setUsageThreshold()

(#Under Construction) See: here for details

Java_sun_management_MemoryPoolImpl_setPoolUsageSensor()

See: here for details

jmm_SetPoolSensor()

See: here for details

MemoryPool::set_usage_sensor_obj()

See: here for details

MemoryPool::set_sensor_obj_at()

See: here for details

Java_sun_management_MemoryPoolImpl_setUsageThreshold0()

See: here for details

jmm_SetPoolThreshold()

See: here for details

ThresholdSupport::is_high_threshold_supported()

See: here for details

ThresholdSupport::is_low_threshold_supported()

See: here for details

ThresholdSupport::set_high_threshold()

See: here for details

ThresholdSupport::set_low_threshold()

See: here for details

LowMemoryDetector::recompute_enabled_for_collected_pools()

See: here for details

LowMemoryDetector::is_enabled()

See: here for details

LowMemoryDetector::detect_low_memory(MemoryPool* pool)

See: here for details

SensorInfo::set_gauge_sensor_level()

See: here for details

SensorInfo::has_pending_requests()

See: here for details

sun.management.MemoryPoolImpl.setCollectionUsageThreshold()

(#Under Construction) See: here for details

Java_sun_management_MemoryPoolImpl_setPoolCollectionSensor

See: here for details

MemoryPool::set_gc_usage_sensor_obj()

See: here for details

Java_sun_management_MemoryPoolImpl_setCollectionThreshold0()

See: here for details

TraceMemoryManagerStats::~TraceMemoryManagerStats()

See: here for details

MemoryService::gc_end()

See: here for details

GCMemoryManager::gc_end()

See: here for details

LowMemoryDetector::detect_after_gc_memory()

See: here for details

SensorInfo::set_counter_sensor_level()

See: here for details

post_allocation_notify()

See: here for details

LowMemoryDetector::detect_low_memory_for_collected_pools()

See: here for details

LowMemoryDetector::is_enabled_for_collected_pools()

See: here for details

MemoryService::track_memory_usage()

See: here for details

LowMemoryDetector::detect_low_memory()

See: here for details

MemoryService::track_code_cache_memory_usage()

See: here for details

MemoryService::track_memory_pool_usage()

See: here for details

LowMemoryDetector::has_pending_requests()

See: here for details

LowMemoryDetector::process_sensor_changes()

See: here for details

SensorInfo::process_pending_requests()

See: here for details

SensorInfo::trigger()

See: here for details

sun.management.Sensor.trigger()

See: here for details

sun.management.PoolSensor.triggerAction()

See: here for details

sun.management.CollectionSensor.triggerAction()

See: here for details

SensorInfo::clear()

See: here for details

sun.management.Sensor.clear()

See: here for details

sun.management.PoolSensor.clearAction()

See: here for details

sun.management.CollectionSensor.clearAction()

See: here for details

sun.management.MemoryPoolImpl.isUsageThresholdExceeded()

(#Under Construction) See: here for details

sun.management.Sensor.isOn()

See: here for details

sun.management.MemoryPoolImpl.getUsageThresholdCount()

(#Under Construction) See: here for details

sun.management.Sensor.getCount()

See: here for details

sun.management.MemoryPoolImpl.isCollectionUsageThresholdExceeded()

(#Under Construction) See: here for details

sun.management.MemoryPoolImpl.getCollectionUsageThresholdCount()

(#Under Construction) See: here for details


This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.