sun.com docs.sun.com My Sun Worldwide Sites

  前の項目 目次 次の項目
第 4 章

プラットフォーム MBean サーバーとプラットフォーム MXBean の使用

この章では、Java Platform, Standard Edition (Java SE プラットフォーム) の一部として提供される MBean サーバーと MXBean について説明します。MBean サーバーと MXBean は、監視および管理の目的で使用できます。Java Management Extensions (JMX) テクノロジの MBean と MBean サーバーについては、第 1 章「Java SE 監視および管理の概要」に概要が記されています。JMX テクノロジについて詳しくは、Java SE プラットフォームの JMX テクノロジ関連ドキュメント を参照してください。

プラットフォーム MBean サーバーの使用

MBean サーバーは、管理アプリケーションから MBean にアクセスできるようにする MBean のリポジトリです。アプリケーションは、MBean に直接アクセスしませんが、その一意の ObjectName を介して、MBean サーバー経由で MBean にアクセスします。MBean サーバーには、インタフェース javax.management.MBeanServer が実装されています。

「プラットフォーム MBean サーバー」は、Java 2 Platform, Standard Edition 5.0 に導入され、Java 仮想マシン (Java VM) に組み込まれた MBean サーバーとなっています。プラットフォーム MBean サーバーは、Java VM で実行する、現在管理下にあるすべてのコンポーネントで共有されます。java.lang.management.ManagementFactory のメソッド getPlatformMBeanServer を使用して、プラットフォーム MBean サーバーにアクセスします。もちろん javax.management.MBeanServerFactory クラスを使用して独自の MBean サーバーを構築することもできます。ただし、通常、MBean サーバーが複数存在する必要はないため、プラットフォーム MBean サーバーの使用をお勧めします。

プラットフォーム MXBean へのアクセス

「プラットフォーム MXBean」は、Java VM の監視および管理を実施する MBean です。各 MXBean では、VM 機能の一部をカプセル化します。第 1 章「Java SE 監視および管理の概要」表 1-1 にプラットフォームで提供する MXBean をすべて一覧で示しています。

管理アプリケーションでは、次の 3 種類の方法で、プラットフォーム MXBean にアクセスできます。

  • 直接アクセス (ManagementFactory クラス経由)。

  • 直接アクセス (MXBean プロキシ経由)。

  • 間接アクセス (MBeanServerConnection クラス経由)。

次の 3 つのセクションでは、これら 3 種類のアクセス方法について説明します。

ManagementFactory クラスを使用したプラットフォーム MXBean へのアクセス

アプリケーションは、自身の Java VM と同一 Java VM で稼働するプラットフォーム MXBean のメソッドに対して直接呼び出しを行うことができます。なお直接呼び出しには、ManagementFactory クラスの static メソッドを使用できます。ManagementFactory には、getClassLoadingMXBean()getGarbageCollectorMXBeans()getRuntimeMXBean() などのさまざまなプラットフォーム MXBean にそれぞれ対応するアクセス用メソッドが用意されています。プラットフォーム MXBean が複数存在する場合、そのメソッドは検出したプラットフォーム MXBean のリストを返します。

たとえば、例 4-1 では、ManagementFactory の static メソッドを使用してプラットフォーム MXBean の RuntimeMXBean を取得し、さらにプラットフォーム MXBean からベンダー名を取得します。

例 4-1 ManagementFactory クラスを経由したプラットフォーム MXBean へのアクセス
RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean();
String vendor = mxbean.getVmVendor(); 

MXBean プロキシを経由したプラットフォーム MXBean へのアクセス

アプリケーションでは、MXBean プロキシを介してプラットフォーム MXBean メソッドを呼び出すこともできます。この呼び出しを行うには、static メソッド ManagementFactory.newPlatformMXBeanProxy() を呼び出して既定の MBean サーバーにメソッドの呼び出しを転送する MXBean プロキシインスタンスの作成が必要となります。アプリケーションでは、通常別の Java VM のプラットフォーム MXBean に対するリモートアクセスを可能とするプロキシを作成します。

たとえば、例 4-2 では、例 4-1 とまったく同じ処理を実行しますが、今回は MXBean プロキシを使用します。

例 4-2 MXBean プロキシを経由したプラットフォーム MXBean へのアクセス
MBeanServerConnection mbs;
...
// Get a MBean proxy for RuntimeMXBean interface
RuntimeMXBean proxy =
    ManagementFactory.newPlatformMXBeanProxy(mbs,
                                             ManagementFactory.RUNTIME_MXBEAN_NAME,
                                             RuntimeMXBean.class);
// Get standard attribute "VmVendor"
String vendor = proxy.getVmVendor();

MBeanServerConnection クラスを使用したプラットフォーム MXBean へのアクセス

アプリケーションは、別の実行中の Java VM のプラットフォーム MBean サーバーに接続されている MBeanServerConnection を経由してプラットフォーム MXBean メソッドを間接的に呼び出すことができます。MBeanServerConnection クラスの getAttribute() メソッドを使用してプラットフォーム MXBean の属性を取得し、MBean の ObjectName と属性名をパラメータとして提供します。

たとえば、例 4-3 では、例 4-1例 4-2 の同じジョブを実行しますが、MBeanServerConnection を介して間接的な呼び出しを行います。

例 4-3 MBeanServerConnection クラスを経由したプラットフォーム MXBean へのアクセス
MBeanServerConnection mbs;
...
try {
  ObjectName oname = new ObjectName(ManagementFactory.RUNTIME_MXBEAN_NAME);
  // Get standard attribute "VmVendor"
  String vendor = (String) mbs.getAttribute(oname, "VmVendor");
} catch (....) {
  // Catch the exceptions thrown by ObjectName constructor
  // and MBeanServer.getAttribute method
  ...
}

Sun Microsystems のプラットフォーム拡張機能の使用

Java VM では、プラットフォームに特化した測定に必要なインタフェースと管理操作を定義することにより管理インタフェースを拡張できます。ManagementFactory クラスの静的ファクトリメソッドは、プラットフォーム拡張機能を備えた MBean を返します。

com.sun.management パッケージには、Sun Microsystems のプラットフォーム拡張機能が含まれています。以下の節では、Sun Microsystems 実装 (OperatingSystemMXBean) からプラットフォーム固有の属性にアクセスする方法の例について説明します。

MXBean の各種属性に対する直接アクセス

例 4-4 では、Sun Microsystems の MXBean インタフェースの 1 つに対して直接アクセスを行っています。

例 4-4 MXBean 属性に対する直接アクセス
com.sun.management.OperatingSystemMXBean mxbean =
  (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();

// Get the number of processors
int numProcessors = mxbean.getAvailableProcessors();

// Get the Sun-specific attribute Process CPU time
long cpuTime = mxbean.getProcessCpuTime();

MBeanServerConnection 経由による MXBean 属性へのアクセス

例 4-5 では、Sun Microsystems の MXBean インタフェースの 1 つに MBeanServerConnection クラス経由でアクセスします。

例 4-5 MBeanServerConnection を経由した MXBean 属性へのアクセス
MBeanServerConnection mbs;

// Connect to a running Java VM (or itself) and get MBeanServerConnection
// that has the MXBeans registered in it
...

try {
    // Assuming the OperatingSystem MXBean has been registered in mbs
    ObjectName oname = new ObjectName(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME);

    // Get standard attribute "Name"
    String vendor = (String) mbs.getAttribute(oname, "Name");

    // Check if this MXBean contains Sun Microsystems' extension
    if (mbs.isInstanceOf(oname, "com.sun.management.OperatingSystemMXBean")) {
        // Get platform-specific attribute "ProcessCpuTime"
        long cpuTime = (Long) mbs.getAttribute(oname, "ProcessCpuTime");
    }
} catch (....) {
    // Catch the exceptions thrown by ObjectName constructor
    // and MBeanServer methods
    ...
}

スレッドコンテンションおよび CPU 時間の監視

プラットフォーム MXBean の ThreadMXBean では、スレッドコンテンションとスレッドの CPU 時間の監視をサポートします。

Sun HotSpot VM では、スレッドコンテンション監視をサポートします。Java VM でスレッドコンテンション監視がサポートされているかどうかを判断するには、ThreadMXBean.isThreadContentionMonitoringSupported() メソッドを使用します。デフォルト時は、スレッドコンテンション監視が無効になっています。有効にするには、setThreadContentionMonitoringEnabled() メソッドを使用します。

Sun HotSpot VM では、ほとんどのプラットフォームにおいてスレッドの CPU 時間の測定をサポートしています。このインタフェースで発生する CPU 時間は、その単位の精度がナノ秒となっていますが、ここではこれほどの精度は要求されません。

Java VM がどのスレッドの CPU 時間の測定もサポートしていることを判断するには、isThreadCpuTimeSupported() メソッドを使用します。Java VM で現スレッドの CPU 時間を測定できるかどうかを判断するには、isCurrentThreadCpuTimeSupported() を使用します。スレッドの CPU 時間の測定をサポートする Java VM では、現スレッドの CPU 時間もサポートします。

Java VM では、スレッドの CPU 時間の測定を無効にすることもできます。スレッドの CPU 時間の測定を有効にするには、isThreadCpuTimeEnabled() メソッドを使用します。スレッドの CPU 時間の測定を有効/無効にするには、setThreadCpuTimeEnabled() メソッドを使用します。

オペレーティングシステムの管理

プラットフォーム MXBean の OperatingSystem では、次に示すようなオペレーティングシステムのリソース情報にアクセスすることができます。

  • プロセス CPU 時間。

  • 物理メモリーの総容量と空き容量。

  • 仮想メモリーの確定容量 (プロセスの実行に使用可能な仮想メモリーの容量)。

  • スワップ空間の総容量および空き容量。

  • オープンファイル記述子の数 (UNIX プラットフォームのみ)。

「JConsole」の「MBean」タブでオペレーティングシステムの MXBean を選択すると、そのプラットフォームの拡張機能を含むすべての属性と動作が表示されます。数値属性の値フィールドをダブルクリックすることにより、この数値属性の長期にわたる値の変化を監視できます。

ロギングの管理

Java SE プラットフォームでは、ロギングを目的とした特殊の MXBean (LoggingMXBean インタフェース) を提供します。

LoggingMXBean では、次のことが実現できます。

  • 指定したロガーと関連付けられているログレベルの名前を取得。

  • 現在登録済みのロガーのリストを取得。

  • 指定したロガーの親の名前を取得。

  • 指定の新しいレベルに指定のロガーを設定。

LoggingMXBean の一意の ObjectName は、java.util.logging:type=Logging です。このオブジェクト名は、LogManager.LOGGING_MXBEAN_NAME に保存されています。

LogManager.getLoggingMXBean() の呼び出しにより取得が可能な単一のグローバルインスタンス LoggingMXBean が用意されています。

MXBean の Logging では、ロガー名のリストを表示する LoggerNames 属性を定義します。使用中のアプリケーションでロガーのリストを検出するには、「MBean」タブで java.util.logging ドメインのロギング MXBean を選択し、LoggerNames 属性の値フィールドをダブルクリックします。ロギング MXBean では、次の 2 種類の処理もサポートしています。

  • getLoggerLevel: 既定のロガーのログレベルを返します。

  • setLoggerLevel: 既定ロガーのログレベルを新たなレベルに設定します。

これらの処理では、ロガー名を第 1 パラメータとして取得します。ロガーのログレベルを変更するには、ロガー名を第 1 パラメータに入力し、そのレベルの名前を setLoggerLevel の第 2 パラメータに入力します。

ローメモリーの検出

メモリーの使用は、メモリーシステムの重要な要素となります。これは、次の問題の可能性を示唆しています。

  • アプリケーションの過度のメモリー消費。

  • 自動メモリー管理システムへの過度の負荷。

  • 潜在的なメモリーリーク。

ローメモリー状態の検出に使用可能なメモリーのしきい値には、「使用量しきい値」と「コレクション使用量しきい値」の 2 種類が用意されています。polling または threshold notification でこれらのしきい値のいずれかを使用して、ローメモリー状態を検出できます。これらの概念についてはすべて次の項で説明します。

メモリーしきい値

メモリープールには、使用量しきい値およびコレクション使用量しきい値の 2 種類のメモリーしきい値を設定することができます。これらのしきい値のどちらか一方は、特定のメモリープールでサポートされない可能性があります。使用量しきい値とコレクション使用量しきい値の値は、「JConsole」の「MBean」タブで設定することができます。

使用量しきい値

使用量しきい値とは、管理可能な、一部のメモリープールの属性を意味します。オーバーヘッドを低く抑えた状態でメモリーの使用状況を監視することができます。しきい値を正の値に設定すると、メモリープールは使用量しきい値をチェックすることができます。使用量しきい値に 0 を設定すると、この使用量しきい値のチェック機能が無効となります。デフォルト値は、Java VM で用意されています。

Java VM は、メモリープールにおいてほぼ適切なタイミングで (一般的にガベージコレクションが発生している間に)、この使用量しきい値のチェック機能を実行します。各メモリープールは、使用量がしきい値を超える場合に常にその使用量しきい値の数を増加します。

一部のメモリープールには、使用量しきい値が適さないことから、isUsageThresholdSupported() メソッドを使用してメモリープールが使用量しきい値をサポートしているかどうかを確認します。たとえば、世代別ガベージコレクタ (HotSpot VM の機能の 1 つ、第 3 章「JConsole の使用」の「ガベージコレクション」を参照) においては、Eden メモリープールからほとんどのオブジェクトが若い世代の方に割り当てられます。なお、Eden プールはその容量がいっぱいになるように設定されています。Eden メモリープールのガベージコレクトにより、そのメモリー領域のほとんどが解放されます。これは、Eden メモリープールに含まれるオブジェクトのほとんどは、ガベージコレクション時にはアクセス不可能な短命なオブジェクトだと予想されるからです。このため、Eden メモリープールは、使用量しきい値をサポートするのに適していません。

コレクション使用量しきい値

コレクション使用量しきい値とは、ガベージコレクトされた一部のメモリープールの属性を意味し、この属性は管理できるようになっています。Java VM でメモリープールのガベージコレクトを行うと、そのメモリープール中の一部のメモリーはそれ以後も引き続き使用中の状態のままとなります。コレクション使用量しきい値により、このメモリーの値を設定することができます。メモリープールでコレクション使用量しきい値がサポートされているかどうかを判断するには、MemoryPoolMXBeanisCollectionUsageThresholdSupported() メソッドを使用します。

Java VM は、ガベージコレクションを行うときに、メモリープールにおけるコレクション使用量しきい値をチェックする場合があります。なお、このチェック機能を有効にするには、このしきい値に正の値を設定します。チェック機能を無効にする場合は、この値に 0 (デフォルト値) を設定します。

使用量しきい値、とコレクション使用量しきい値は、いずれも「JConsole」の「MBean」タブで設定することができます。

Memory MXBean

プラットフォーム MemoryMXBean を使用してメモリーのさまざまなしきい値を管理することができます。MemoryMXBean では、次の 4 つの属性を定義します。

  • HeapMemoryUsage: 現在のヒープメモリーの使用状況を示す読み取り専用の属性です。

  • NonHeapMemoryUsage: 非ヒープメモリーの使用状況を示す読み取り専用の属性です。

  • ObjectPendingFinalizationCount: ファイナライズを保留しているオブジェクトの数を示す読み取り専用の属性です。

  • Verbose: ガベージコレクション (GC) の冗長トレース設定を示すブール型の属性です。この値は動的に設定することができます。GC の冗長トレースは、Java VM を開始する際に指定した位置に表示されます。Hotspot VM の GC 冗長出力におけるデフォルトの位置は、stdout となります。

メモリー MXBean では、処理 gc を 1 つサポートしています。これにより、明示的にガベージコレクションを要求できます。

メモリー MXBean のインタフェースに関する詳細は、java.lang.management.MemoryMXBean 仕様に定義されています。

Memory Pool MXBean

プラットフォーム MXBean の MemoryPoolMXBean では、メモリーのしきい値を管理するために一連の処理を定義します。

  • getUsageThreshold()

  • setUsageThreshold(long threshold)

  • isUsageThresholdExceeded()

  • isUsageThresholdSupported()

  • getCollectionUsageThreshold()

  • setCollectionUsageThreshold(long threshold)

  • isCollectionUsageThresholdSupported()

  • isCollectionUsageThresholdExceeded()

各メモリープールには、ローメモリーの検出をサポートする上で、使用量しきい値およびコレクション使用量しきい値の 2 種類のメモリーしきい値が用意されています。これらのしきい値のどちらか一方は、特定のメモリープールでサポートされない可能性があります。詳しくは、MemoryPoolMXBean クラスの API リファレンスを参照してください。

ポーリング

アプリケーションでは、すべてのメモリープール共通の getUsage() メソッド、または使用量しきい値をサポートするメモリープール専用の isUsageThresholdExceeded() メソッドを呼び出すことにより、アプリケーション自体のメモリー使用量を継続的に監視できます。

例 4-6 では、タスクの配置と処理のために設けられたスレッドが使用されています。各間隔では、メモリーの使用量に基づき新しいタスクの受け取りや処理を行うかどうかを判断します。メモリーの使用量がその使用量しきい値を上回る場合、そのメモリーの使用量がしきい値以下となるまで別の VM に未処理のタスクを再配置し、新しいタスクを受け取らないようにします。

例 4-6 ポーリングの使用
pool.setUsageThreshold(myThreshold);
....
boolean lowMemory = false;
while (true) {
  if (pool.isUsageThresholdExceeded()) {
    lowMemory = true;
    redistributeTasks();  // redistribute tasks to other VMs
    stopReceivingTasks();  // stop receiving new tasks
  } else {
    if (lowMemory) { // resume receiving tasks
      lowMemory = false;
      resumeReceivingTasks();
    }
    // processing outstanding task
    ...
  }
  // sleep for sometime
  try {
    Thread.sleep(sometime);
  } catch (InterruptedException e) {
    ...
  }
}      

例 4-6 では、メモリーの使用量がその使用量しきい値を一時的に下回る場合と、2 つの繰り返し間においてメモリーの使用量がしきい値を上回ったままの状態である場合の区別がありません。getUsageThresholdCount() から返される使用量しきい値の数を使用して、メモリーの使用量が、2 つのポール間でしきい値を下回る値を返すかどうかを判断します。

代わりにコレクション使用量しきい値をテストするには、前述と同じ方法で isCollectionUsageThresholdSupported()isCollectionThresholdExceeded()getCollectionUsageThreshold() メソッドを使用します。

しきい値通知

MemoryMXBean でメモリープールの使用量がそのしきい値に到達しているか、上回っていることが検出された場合は、「使用量しきい値超過」通知が発行されます。使用量がしきい値を下回り、再び上回るまで、MemoryMXBean は、別の使用量しきい値超過通知を発行しません。同様に、ガベージコレクション後のメモリーの使用量が、コレクション使用量しきい値を上回る場合、MemoryMXBean では、コレクション使用量しきい値超過通知を発行します。

例 4-7 は、例 4-6 と同じロジックを使用していますが、ローメモリー状態を検出するために使用量しきい値を示す通知を行っています。通知を受け取ると、リスナーは、未処理タスクの再配置、新タスクの受け入れ拒否、新タスクの再受け入れなどのアクションを実行するために別のスレッドの通知を行います。

一般に、以後の通知の遅れを回避するために、処理量を最小限にする handleNotification メソッドを設計する必要があります。時間を浪費するアクションは別のスレッドにおいて実行するようにしてください。複数のスレッドで通知リスナーを同時に呼び出すことができるため、リスナーは、タスクが正常に実行されるようにそのタスクを同期させる必要があります。

例 4-7 しきい値通知の使用
class MyListener implements javax.management.NotificationListener {
  public void handleNotification(Notification notification, Object handback)  {
    String notifType = notification.getType();
    if (notifType.equals(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED)) {
      // potential low memory, redistribute tasks to other VMs & stop receiving new tasks.
      lowMemory = true;
      notifyAnotherThread(lowMemory);
    }
  }
}

// Register MyListener with MemoryMXBean
MemoryMXBean mbean = ManagementFactory.getMemoryMXBean();
NotificationEmitter emitter = (NotificationEmitter) mbean;
MyListener listener = new MyListener();
emitter.addNotificationListener(listener, null, null);

このメモリープールで使用量しきい値をサポートするものと仮定する場合、しきい値 (値を上回ると新タスクを受け入れなくなるしきい値) をある値 (バイト数表記) に設定することができます。

pool.setUsageThreshold(myThreshold);

この後、使用量しきい値の検出が有効となり、MyListener で通知が行われるようになります。

前の項目 目次 次の項目
会社情報 連絡先 利用規約 プライバシー Copyright 1994-2006 Sun Microsystems, Inc.