プライマリ・コンテンツに移動
Java Platform, Standard Edition Java Management Extensionsガイド
リリース9
E91921-01
目次へ移動
目次

前
次

10 JMX APIの基本要素

この章では、Java Management Extensions (JMX) APIのコア・コンポーネントである管理対象Bean (MBean)について説明します。

MBeanはJavaBeanTMに似た管理対象Javaオブジェクトであり、その設計パターンはJMX仕様の計測レベルの規定に従います。MBeanは、管理対象となるデバイス、アプリケーションまたは任意のリソースを表示できます。MBeanは管理インタフェース、すなわち読込みと書込みの一方または両方が可能な属性セットと、呼出し可能な操作セット、および自己記述を開示しています。管理インタフェースは、MBeanインスタンスの生存期間を通じて変化しません。また、MBeanは、定義済みの特定のイベントが起こった場合に通知を発行します。

JMX仕様では、標準MBean動的MBeanopen MBean、およびmodel MBeanという4種類のMBeanを定義しています。このチュートリアルの例では、もっとも単純なMBeanである標準MBeanについて説明します。

標準MBean

標準MBeanは、JavaインタフェースSomethingMBeanとそのインタフェースを実装するJavaクラスSomethingを記述することで定義できます。インタフェースのすべてのメソッドは、MBeanの属性か操作のいずれかを定義します。デフォルトでは、すべてのメソッドは操作を定義します。属性と操作は、特定の設計パターンに従った簡単なメソッドです。標準MBeanは、開示されたすべての属性と操作のメソッドを一覧にしたMBeanインタフェースと、このインタフェースを実装し、計測されたリソースに機能を割り当てるクラスから構成されます。

以降のセクションでは、標準MBeanの例と、MBeanを管理する簡単なJMXエージェントについて説明します。コード・サンプルはJMXの基本要素にあります。例をディレクトリwork_dir/jmx_examples/Essential/com/example/mbeansから実行できます。

MBeanインタフェース

HelloMBeanという基本的なMBeanインタフェースの例を、コード例2-1 MBeanインタフェース、HelloMBeanに示します。

コード例2-1 MBeanインタフェース、HelloMBean

 
package com.example.mbeans; 
 
public interface HelloMBean { 
 
    public void sayHello(); 
    public int add(int x, int y); 
 
    public String getName(); 
 
    public int getCacheSize(); 
    public void setCacheSize(int size); 
} 
 

MBeanインタフェースは、このインタフェースを実装するJavaクラスの名前の後にMBeanを加えて名前を構成します。このインタフェースがHelloMBeanです。このインタフェースを実装するHelloクラスについては、MBeanの実装で説明します。

JMX仕様によると、MBeanインタフェースは、名前と型の指定された読込み可能で、場合によっては書込み可能な属性と、MBeanが管理するアプリケーションにより呼び出すことが可能な、名前と型の指定された操作から構成されます。コード例2-1 MBeanインタフェース、HelloMBeanに示したHelloMBeanインタフェースでは、2つの操作(Javaメソッドadd()sayHello())を宣言しています。

HelloMbeanで宣言される2つの属性のうち、Nameは読込み専用の文字列で、CacheSizeは読み込みと書込みの両方が可能な整数です。取得メソッドと設定メソッドは、管理対象アプリケーションに属性の値へのアクセスと、場合によっては値の変更を許可するために宣言されます。JMX仕様に定義されるように、取得メソッドはgetから名前が始まり、voidを返さないすべてのpublicメソッドです。取得メソッドを使用すると、マネージャは返されたオブジェクトの型と一致する属性の値を読み込むことができます。設定メソッドは名前がsetから始まり、単一のパラメータをとるすべてのpublicメソッドです。設定メソッドを使用すると、マネージャはパラメータと同じ型の値を属性に新たに書き込むことができます。

次のセクションでは、これらの操作および属性の実装を説明します。

MBeanの実装

コード例2-2 MBeanの実装クラス、Helloに示したHelloクラスは、HelloMBeanを実装します。

コード例2-2 MBeanの実装クラス、Hello

 
package com.example.mbeans; 
 
public class Hello implements HelloMBean { 
    public void sayHello() { 
        System.out.println("hello, world"); 
    } 
 
    public int add(int x, int y) { 
        return x + y; 
    } 
 
    public String getName() { 
        return this.name; 
    } 
 
 
    public int getCacheSize() { 
        return this.cacheSize; 
    } 
 
    public synchronized void setCacheSize(int size) { 
        this.cacheSize = size; 
 
        System.out.println("Cache size now " + this.cacheSize); 
    } 
 
    private final String name = "Reginald"; 
    private int cacheSize = DEFAULT_CACHE_SIZE; 
    private static final int DEFAULT_CACHE_SIZE = 200; 
} 
 

例2-2では、JavaクラスHelloは、HelloMBeanで宣言された操作と属性を定義します。この例からわかるように、例sayHello()add()の操作はきわめて簡単ですが、実際の操作は必要に応じて簡単にも、複雑なものにもできます。

Name属性を取得するメソッドと、cacheSize属性を取得し設定するメソッドも定義されます。この例では、Name属性の値は変わりませんが、実際の場面では、管理対象リソースの実行により変わる場合があります。たとえば、属性は稼動時間やメモリーの使用量などの統計を表す場合があります。ここでは、属性は「Reginald」という名前だけです。

setCacheSizeメソッドを呼び出すと、cacheSize属性の値を、宣言されたデフォルトの値200から変更できます。実際には、cacheSize属性を変更する場合は、エントリの破棄や新しいエントリの割り当てなど、ほかの操作を実行しなければなりません。この例では、キャッシュ・サイズが変更されたことを確認するメッセージのみが出力されますが、println()を呼び出す操作のかわりに、より複雑な操作を定義できます。

Hello MBeanとそのインタフェースを定義すると、次のセクションに示すように、Hello MBeanとインタフェースで表されるリソースを、Hello MBeanとインタフェースを使用して管理できます。

リソースの管理

Java Management Extensions Technology User's Guideに説明されているように、MBeanによってリソースが計測された後は、そのリソースの管理はJMXエージェントにより実行されます。

JMXエージェントのコア・コンポーネントはMBeanサーバーです。MBeanサーバーは、MBeanが登録されている管理オブジェクト・サーバーのことです。MBeanサーバー実装の詳細は、MBeanServerインタフェースのAPIドキュメントを参照してください。JMXエージェントには、MBeanを管理するための一連のサービスも含まれます。コード例2-3 JMXエージェントの作成では、Mainという基本的なJMXエージェントを示しています。

コード例2-3 JMXエージェントの作成

 
package com.example.mbeans; 
 
import java.lang.management.*; 
import javax.management.*; 
 
public class Main { 
 
   public static void main(String[] args) throws Exception { 
 
      MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 
 
      ObjectName name = new ObjectName("com.example.mbeans:type=Hello"); 
 
      Hello mbean = new Hello(); 
 
      mbs.registerMBean(mbean, name); 
 
      System.out.println("Waiting forever..."); 
      Thread.sleep(Long.MAX_VALUE); 
   } 
} 
 

例2-3では、JMXエージェントMainは、まずjava.lang.management.ManagementFactoryクラスのgetPlatformMBeanServer()メソッドを呼び出して、プラットフォーム上で稼動する任意のMBeanサーバーを取得します。プラットフォーム上で稼動中のMBeanが存在しない場合、getPlatformMBeanServer()によりJMXメソッドMBeanServerFactory.createMBeanServer()が呼び出され、自動的に稼動中のMBeanが作成されます。Mainで取得されるMBeanServerインスタンスは、mbsの名前が付けられます。

次に、Mainは作成するMBeanインスタンスのために、オブジェクト名を定義します。すべてのJMX MBeanにオブジェクト名が定義される必要があります。オブジェクト名はJMXクラスObjectNameのインスタンスであり、ドメインキー・プロパティのリストを必ず含めるなど、JMX仕様で定義される構文に従う必要があります。この構文の詳細は、ObjectNameクラスのAPIドキュメントを参照してください。Mainで定義されるオブジェクト名、nameでは、ドメインはcom.example.mbeans (MBeanの例が格納されたパッケージ)です。また、キー・プロパティはこのオブジェクトがHello型であることを宣言します。

Helloオブジェクトのインスタンス、mbeanが作成されます。このHelloオブジェクトは、MBeanの実装で定義されたMBean Helloのインスタンスです。

Helloオブジェクトmbeanは、オブジェクト名nameを使用してMBean server mbsにMBeanとして登録されます。このために、オブジェクトとオブジェクト名を渡してJMXメソッドMBeanServer.registerMBean()を呼び出します。

Hello MBeanをMBeanサーバーに登録したあと、Mainは管理操作がHelloで実行されるのを待機します。この例の範囲では、これらの管理操作はsayHello()add()を呼び出し、属性値を取得および設定しています。

標準MBeanの例題の実行

例題のクラスを検証した後、例題を実行できます。Java Platform, Standard EditionにはJConsoleという管理およびモニタリング・コンソールが含まれており、この例ではMBeanとの対話に使用されています。JConsoleはJavaSE_HOME/bin/jconsoleにあります。JavaSE_HOMEはJava Platform, Standard Edition (Java SEプラットフォーム)がインストールされたディレクトリです。

例題を実行するには、次の手順を実行します。

  1. JMXの基本要素にあるソース・コードをwork_dir/jmx_examples/Essentialにコピーします。

  2. Javaクラスの例をコンパイルします。

    $ javac com/example/mbeans/*.java

  3. Mainアプリケーションを起動します。

    $ java com.example.mbeans.Main

    何かの発生を待機中のMainに関する確認が表示されます。

  4. 同じマシンの別の端末ウィンドウで、JConsoleを起動します。

    $ jconsole

    JConsoleツールが開き、接続可能な稼動中のJMXエージェントのリストが表示されます。

  5. 「新規接続」ウィンドウのリストからcom.example.mbeans.Mainを選択し、「接続」をクリックします。

    プラットフォームの現在のアクティビティのサマリーが表示されます。

  6. MBean」タブをクリックします。

    このパネルに、現在MBeanサーバーに登録されているすべてのMBeanが表示されます。

  7. 左フレームにあるMBeanツリーのcom.example.mbeansノードを展開します。

    Mainで作成され、登録されたMBean Helloの例が表示されます。Helloをクリックすると、関連するAttributesおよびOperationsノードがMBeanツリーに表示されます。

  8. MBeanツリー内のHello MBeanノードをクリックしてHello MBeanのメタデータとそれに関連する記述子を表示します。
  9. MBeanツリーにあるHello MBeanのAttributesノードをクリックします。

    Helloクラスで定義されたMBean属性が表示されます。

  10. CacheSize属性の値を150に変更します。

    Mainを起動した端末ウィンドウで、この属性の変更を確認が表示されます。

  11. MBeanツリーにあるHello MBeanのOperationsノードをクリックします。

    ここで、Hello MBeanで宣言された2つの操作、sayHello()add()が表示されます。

  12. sayHello」ボタンをクリックして、sayHello()操作を起動します。

    メソッドが正常に呼び出されたことがJConsoleのダイアログ・ボックスに通知され、Mainが起動している端末のウィンドウに「hello, world」というメッセージが表示されます。

  13. add()操作で加算する2つの整数を指定し、「add」ボタンをクリックします。

    「JConsole」ダイアログ・ボックスに解答が通知されます。

  14. 接続」をクリックし、次に「終了」をクリックして、JConsoleを終了します。

通知の送信

MBeanは状態の変化、検出されたイベント、または問題などを知らせる通知を生成します。

MBeanが通知を生成するためには、インタフェースNotificationBroadcasterか、またはそのサブインタフェースNotificationEmitterを実装している必要があります。通知の送信に必要な操作は、クラスjavax.management.Notificationまたはサブクラス(AttributeChangedNotificationなど)のインスタンスを構築し、それをNotificationBroadcasterSupport.sendNotificationに渡すだけです。

すべての通知に発行元があります。発行元は通知を発行したMBeanのオブジェクト名です。

すべての通知にはシーケンス番号が割り振られています。順序が重要な意味を持つ場合、および通知が間違った順序で処理される危険性がある場合、この番号を使用して同じソースから到着した通知を並べることができます。シーケンス番号をゼロにしてもかまいませんが、特定のMBeanから通知が到着するたびにインクリメントする方が適切です。

標準MBeanがディレクトリwork_dir/jmx_examples/Notification/com/example/mbeansで通知を発行する例を考えてみます。この例は、標準MBeanで示した例題と基本的には同じですが、Hello MBeanがNotificationBroadcasterインタフェースを実装している点で異なっています。

NotificationBroadcasterインタフェース

前述のように、この例題と標準MBeanで示した例題の唯一の違いは、MBeanの実装により通知の送信ができるという点です。コード例2-4 MBeanの通知の実装に示したように、通知はNotificationBroadcasterインタフェースを実装することで起動します。

コード例2-4 MBeanの通知の実装

 
package com.example.mbeans; 
 
import javax.management.*; 
 
public class Hello 
        extends NotificationBroadcasterSupport implements HelloMBean { 
 
    public void sayHello() { 
        System.out.println("hello, world"); 
    } 
 
    public int add(int x, int y) { 
        return x + y; 
    } 
 
    public String getName() { 
        return this.name; 
    } 
 
    public int getCacheSize() { 
        return this.cacheSize; 
    } 
 
    public synchronized void setCacheSize(int size) { 
        int oldSize = this.cacheSize; 
        this.cacheSize = size; 
 
        System.out.println("Cache size now " + this.cacheSize); 
 
        Notification n = 
            new AttributeChangeNotification(this, 
                                            sequenceNumber++, 
                                            System.currentTimeMillis(), 
                                            "CacheSize changed", 
                                            "CacheSize", 
                                            "int", 
                                            oldSize, 
                                            this.cacheSize); 
 
        sendNotification(n); 
    } 
 
    @Override 
    public MBeanNotificationInfo[] getNotificationInfo() { 
        String[] types = new String[] { 
            AttributeChangeNotification.ATTRIBUTE_CHANGE 
        }; 
        String name = AttributeChangeNotification.class.getName(); 
        String description = "An attribute of this MBean has changed"; 
        MBeanNotificationInfo info = 
            new MBeanNotificationInfo(types, name, description); 
        return new MBeanNotificationInfo[] {info}; 
    } 
 
    private final String name = "Reginald"; 
    private int cacheSize = DEFAULT_CACHE_SIZE; 
    private static final int DEFAULT_CACHE_SIZE = 200; 
 
    private long sequenceNumber = 1; 
} 
 

コード例2-4 MBeanの通知の実装に示したように、このHello MBeanの実装によりNotificationBroadcasterSupportクラスが拡張され、このクラス自体にNotificationEmitterインタフェースが実装されます。

操作と属性の設定方法は以前と同様ですが、唯一変わったのはcacheSize属性の設定メソッドがoldSizeという新しい値を定義する点です。この値は設定操作の前にcacheSize属性の値を記録します。

通知は、javax.management.Notificationを拡張するJMXクラスAttributeChangeNotificationのインスタンスnから構築されます。この通知はAttributeChangeNotificationにパラメータとして渡される次の情報に基づいて、setCacheSize()メソッドの定義内で構築されます。

  • Hello MBeanなどの通知の発行元のオブジェクト名。簡単にthisと表される
  • シーケンス番号。この例では、ロング名sequenceNumberが使われ、1に設定されたあと、1つずつインクリメントする
  • タイムスタンプ
  • 通知メッセージの内容
  • 変更された属性の名前。この場合はcacheSize
  • 変更された属性の型
  • 古い属性値。この場合はoldSize
  • 新しい属性値。この場合はthis.cacheSize

この後、通知nがNotificationBroadcasterSupport.sendNotification()メソッドに渡されます。

最後に、MBeanNotificationが定義され、特定のJavaクラスの通知、この場合はAttributeChangeNotificationに対してMBeanが発行した別の通知インスタンスの特性が説明されます。

MBeanインタフェースHelloMBeanとJMXエージェントMainは、前出の例で使用されたものと同じです。

MBeanの通知の例題の実行

クラスの例題を検証したあと、今度は例題を実行します。この例では、JConsoleを使用してHello MBeanと対話します。この例題を実行するには、次の手順を実行します。

  1. JMX MBeanの通知からwork_dir/jmx_examples/Notificationにソース・コードをコピーします。

  2. Javaクラスの例をコンパイルします。

    $ javac com/example/mbeans/*.java
  3. Mainアプリケーションを起動します。

    $ java com.example.mbeans.Main

    何かの発生を待機中のMainに関する確認が表示されます。

  4. 同じマシンの別の端末ウィンドウで、JConsoleを起動します。

    $ jconsole

    JConsoleツールが開き、接続可能な稼動中のJMXエージェントのリストが表示されます。

  5. 新規接続」ウィンドウのリストからcom.example.mbeans.Mainを選択し、「接続」をクリックします。

    プラットフォームの現在のアクティビティのサマリーが表示されます。

  6. MBean」タブをクリックします。

    このパネルに、現在MBeanサーバーに登録されているすべてのMBeanが表示されます。

  7. 左フレームにあるMBeanツリーのcom.example.mbeansノードを展開します。

    Mainで作成され、登録されたMBean Helloの例が表示されます。Helloをクリックすると、関連するAttributesOperations、およびNotificationsノードがMBeanツリーに表示されます。

  8. MBeanツリーにあるHello MBeanノードをクリックします。

    これによって、MBeanのメタデータと関連する記述子が表示されます。

  9. MBeanツリーにあるHello MBeanのNotificationsノードをクリックします。

    空のパネルが表示されます。

  10. 「Subscribe」ボタンをクリックします。

    現在の受領通知数(0)が、Notificationsノード・ラベルに表示されます。

  11. MBeanツリーにあるHello MBeanのAttributesノードをクリックし、CacheSize属性を150に変更します。

    Mainを起動した端末ウィンドウで、この属性の変更を確認が表示されます。また、Notificationsノードに表示される受領通知数が1に変更されています。

  12. MBeanツリーにあるHello MBeanのNotificationsノードをふたたびクリックします。

    送信された通知の詳細が表示されます。

  13. 接続」をクリックし、次に「終了」をクリックして、JConsoleを終了します。

MXBeanの導入

MXBeanは新しいタイプのMBeanで、定義済みの型セットだけを参照するMBeanのコーディングが簡単にできます。この方法なら、リモート・クライアントを含むクライアントは、MBeanの型を示すモデル固有のクラスにアクセスしなくても、MBeanを利用できます。MXBeanは、クライアントに特にバンドル操作の構成を要求することなく、関連する値をバンドルする便利な手法を提供します。

標準MBeanの場合と同様、MXBeanを定義するには、SomethingMXBeanというJavaインタフェースとそのインタフェースを実装するJavaクラスを記述します。ただし、標準MBeanとは異なり、MXBeanではそのJavaクラスをSomethingと呼ぶ必要はありません。このインタフェース内の各メソッドは、MXBeanの属性と操作のいずれかを定義します。そのほか、@MXBean注釈を使用する場合は、インタフェース名にMXBean拡張子を付ける代わりに、Javaインタフェースに注釈を付けることもできます。

MXBeanは、クライアントに特にバンドル操作の構成を要求することなく、MBeanと対話しながら関連する値をMBeanにバンドルする便利な手法を提供します。MXBeanはJava 2 Platform, Standard Edition (J2SE) 5.0のjava.lang.managementパッケージに入っています。Java SE 6プラットフォームでは、java.lang.managementで定義された標準セットだけでなく、ユーザー自身のMXBeanを定義できます。

MXBeanの主な意図は、MXBeanインタフェースで参照されるjava.lang.management.MemoryUsageなどの型(この場合はjava.lang.management.MemoryMXBean)を標準型セットにマップすることにあります。その標準型セットはOpen Typeと呼ばれ、javax.management.openmbeanパッケージで定義されます。厳密なマッピングの規則は「MXBeanの仕様」に記載されていますが、大ざっぱにいえば、intStringのような単純な型に変更はなく、MemoryUsageのような複雑な型はCompositeDataSupport標準型にマップされます。

jmx_examples.zipファイルをダウンロードして解凍すると、MXBeanの操作を説明したサンプル・プログラムがwork_dir/jmx_examples/MXBean/com/example/mxbeansディレクトリに作成されます。MXBeanのサンプルには、次のファイルが含まれています。

  • QueueSamplerMXBeanインタフェース。
  • MXBeanインタフェースを実装するQueueSamplerクラス。
  • QueueSample Javaの型で、MXBeanインタフェース内のgetQueueSample()メソッドによって返されます。
  • Main、サンプルを設定して実行するプログラム。

MXBeanのサンプルには、次のアクションが含まれています。

  • type Queue<String>のリソースを管理する、単純なMXBeanを定義する。
  • 呼び出されるとキューのスナップショットを作成するMXBeanの取得メソッドgetQueueSampleを宣言し、次の値をバンドルするJavaクラスQueueSampleを返す。
  • スナップショットが作成された時間。
  • キューのサイズ。
  • 指定された時間のキューの先頭。
  • MBeanサーバーにMXBeanを登録する。

QueueSamplerMXBeanインタフェース

コード例2-5 QueueSamplerMXBeanインタフェースは、QueueSamplerMXBeanインタフェースのサンプル・コードを示しています。

コード例2-5 QueueSamplerMXBeanインタフェース

 
package com.example.mxbeans; 
 
public interface QueueSamplerMXBean { 
    public QueueSample getQueueSample(); 
    public void clearQueue(); 
} 
 

この例からわかるように、MXBeanインタフェースの宣言は標準MBeanの宣言とまったく同じです。QueueSamplerMXBeanインタフェースでは、getQueueSampleclearQueueという2つの操作を宣言しています。

QueueSamplerクラス

QueueSamplerクラスは、コード例2-6 QueueSamplerクラスに示すように、QueueSamplerMXBeanインタフェースを実装しています。

コード例2-6 QueueSamplerクラス

package com.example.mxbeans; 
 
import java.util.Date; 
import java.util.Queue; 
 
public class QueueSampler implements QueueSamplerMXBean { 
     
    private Queue<String> queue; 
     
    public QueueSampler(Queue<String> queue) { 
       this.queue = queue; 
    } 
     
    public QueueSample getQueueSample() { 
        synchronized (queue) { 
            return new QueueSample(new Date(), queue.size(), queue.peek()); 
        } 
    } 
     
    public void clearQueue() { 
        synchronized (queue) { 
            queue.clear(); 
        } 
    } 
} 
 

MXBeanインタフェースで宣言されたMXBean操作のgetQueueSample()およびclearQueue()は、QueueSamplerで定義されます。getQueueSample()操作は単純に、QueueSample Java型(java.util.Queueメソッドのpeek()およびsize()によって返された値を使用して作成)のインスタンスとjava.util.Dateのインスタンスを返します。

QueueSampleクラス

QueueSamplerによって返されたQueueSampleインスタンスは、コード例2-7 QueueSamplerクラスに示したQueueSampleクラスで定義されます。

コード例2-7 QueueSampleクラス

package com.example.mxbeans; 
 
import java.beans.ConstructorProperties; 
import java.util.Date; 
 
public class QueueSample { 
     
    private final Date date; 
    private final int size; 
    private final String head; 
     
    @ConstructorProperties({"date", "size", "head"}) 
    public QueueSample(Date date, int size, String head) { 
        this.date = date; 
        this.size = size; 
        this.head = head; 
    } 
     
    public Date getDate() { 
        return date; 
    } 
     
    public int getSize() { 
        return size; 
    } 
     
    public String getHead() { 
        return head; 
    } 
} 
 

QueueSampleクラスでは、MXBeanフレームワークがQueueSampleの取得メソッドをすべて呼び出して、指定されたインスタンスをCompositeDataに変換し、@ConstructorProperties注釈を使用して、CompositeDataからQueueSampleインスタンスを再構築します。

MXBeanの作成とMBeanサーバーへの登録

MXBeanインタフェースとこれを実装するクラス、および返されるJava型を定義したら、次はMXBeanを作成してMBeanサーバーに登録する必要があります。これらのアクションは、サンプル・クラスMainによって行われます。

コード例2-8 MXBeanのMainクラスの例

package com.example.mxbeans; 
 
import java.lang.management.ManagementFactory; 
import java.util.Queue; 
import java.util.concurrent.ArrayBlockingQueue; 
import javax.management.MBeanServer; 
import javax.management.ObjectName; 
 
public class Main { 
 
    public static void main(String[] args) throws Exception { 
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 
         
        ObjectName name = 
                new ObjectName("com.example.mxbeans:type=QueueSampler"); 
         
        Queue<String> queue = new ArrayBlockingQueue<String>(10); 
        queue.add("Request-1"); 
        queue.add("Request-2"); 
        queue.add("Request-3"); 
        QueueSampler mxbean = new QueueSampler(queue); 
         
        mbs.registerMBean(mxbean, name); 
         
        System.out.println("Waiting..."); 
        Thread.sleep(Long.MAX_VALUE); 
    } 
} 
 

Mainクラスは、プラットフォームMBeanサーバーを取得して、MXBean QueueSamplerのオブジェクト名を作成し、QueueSampler MXBeanのQueueインスタンスを作成して処理します。次に、このQueueインスタンスを、新規作成されたQueueSampler MXBeanに送ります。これで標準MBeanとまったく同じように、MXBeanがMBeanサーバーに登録されます。

MXBeanの例題の実行

MXBeanの例題を実行するには、次の手順を実行します。

  1. MXBeansからwork_dir/jmx_examples/MXBeanにソース・コードをコピーします。

  2. Javaクラスの例をコンパイルします。

    $ javac com/example/mxbeans/*.java
  3. Mainアプリケーションを起動します。

    $ java com.example.mxbeans.Main

    何かの発生を待機中のMainに関する確認が表示されます。

  4. 同じマシンの別の端末ウィンドウで、JConsoleを起動します。

    $ jconsole

    JConsoleツールが開き、接続可能な稼動中のJMXエージェントのリストが表示されます。

  5. 新規接続」ウィンドウのリストからcom.example.mxbeans.Mainを選択し、「接続」をクリックします。

    プラットフォームの現在のアクティビティのサマリーが表示されます。

  6. MBean」タブをクリックします。

    このパネルに、現在MBeanサーバーに登録されているすべてのMBeanが表示されます。

  7. 左フレームにあるMBeanツリーのcom.example.mxbeansノードを展開します。

    Mainで作成され、登録されたMBean QueueSamplerの例が表示されます。QueueSamplerをクリックすると、関連するAttributesおよびOperationsノードがMBeanツリーに表示されます。

  8. Attributesノードを選択します。

    右ペインにQueueSample属性とそのjavax.management.openmbean.CompositeDataSupportの値が表示されます。

  9. CompositeDataSupport値をダブルクリックします。

    MXBeanフレームワークがQueueSampleインスタンスをCompositeDataに変換したため、QueueSampleの値であるdatehead、およびsizeが表示されます。QueueSamplerをMXBeanではなく標準MBeanとして定義した場合、QueueSampleクラスはそのクラス・パスには存在しないのでJConsoleからは見つかりません。QueueSamplerが標準MBeanの場合、QueueSample属性値を抽出するとClassNotFoundExceptionが返されます。このように、JConsoleのように汎用的なJMXクライアントでJMXエージェントに接続するときにMXBeanを使用すると便利です。

  10. Operationsノードを選択します。

    clearQueue操作を呼び出すボタンが表示されます。

  11. clearQueue」ボタンをクリックします。

    メソッドの呼出しに成功したことが通知されます。

  12. Attributesノードをもう一度選択し、CompositeDataSupport値をダブルクリックします。

    これでキューがリセットされます。

  13. 接続」をクリックし、次に「終了」をクリックして、JConsoleを終了します。

この例では、JConsoleがJMXクライアントとして使用されましたが、JMXクライアントの自作プログラムからMXBeanにアクセスする場合は次の2つの方法のどちらかで行います。

  • 一般的には次のコードを使用します。

    MBeanServer mbs = ...whatever...; 
    ObjectName name = new ObjectName("com.example.mxbeans:type=QueueSampler"); 
    CompositeData queueSample = (CompositeData) mbs.getAttribute(name,  
                                 "QueueSample"); 
    int size = (Integer) queueSample.get("size"); 
    
  • プロキシ経由では次のコードを使用します。

    MBeanServer mbs = ...whatever...; 
    ObjectName name = new ObjectName("com.example.mxbeans:type=QueueSampler"); 
    QueueSamplerMXBean proxy = JMX.newMXBeanProxy(mbs, name,  
                                                  QueueSamplerMXBean.class); 
    QueueSample queueSample = proxy.getQueueSample(); 
    int size = queueSample.getSize(); 
    

    このコードでは、newMXBeanProxyメソッドを使用してMXBeanプロキシを作成しています。newMBeanProxyという等価のメソッドがあるのは、ほかの型のMBeanで使用するプロキシを作成するためです。newMBeanProxyおよびnewMXBeanProxyメソッドの使用法はまったく同じです。

MBean記述子

記述子によって、MBeanに関する追加情報を管理クライアントに提供できます。たとえば、MBean属性に関する記述子で計測単位や最大値と最小値を示す場合もあります。Java SE 6の時点で、記述子はJMX APIに含まれており、どのMBeanでも使用可能です。

記述子は、任意のメタデータをMBeanに追加する場合に便利です。記述子はJMX APIに必ずありますが、Java SE 6まではModel MBeanと別に使用することはできません。

MBean*Infoクラス(MBeanInfoMBeanAttributeInfoなど)のほとんどのコンストラクタの場合、それぞれに共通するパラメータと追加パラメータjavax.management.Descriptorを持つ並列コンストラクタが存在します。OpenMBean*InfoSupportの場合も同様です。MBean*InfoおよびOpenMBean*InfoSupportクラスには、getDescriptor()メソッドが含まれています。

Open MBeansは、OpenMBeanParameterInfoおよびOpenMBeanAttributeInfoのメソッドgetDefaultValue()getLegalValues()getMaxValue()getMinValue()から、デフォルトに関する情報と有効な値を返します。今回、この情報が対応する記述子にも含まれるようになりました。また、他のMBean型も自身の記述子にこの情報を返すことができます。

jmx_examples.zipファイルをダウンロードして解凍すると、MBean記述子を説明したサンプル・プログラムがwork_dir/jmx_examples/Descriptors/com/example/mxbeansディレクトリに作成されます。MBean記述子のサンプルには、次のファイルが含まれています。

  • Author。MBeanインタフェースの著者名を示す注釈。
  • DisplayName。MBeanインタフェースのメソッドの表示名を示す注釈。
  • Main、サンプルを設定して実行するプログラム。
  • QueueSamplerMXBeanインタフェース。
  • MXBeanインタフェースを実装するQueueSamplerクラス。
  • QueueSample Javaの型で、MXBeanインタフェース内のgetQueueSample()メソッドによって返されます。
  • Version。MBeanインタフェースの現在のバージョンを示す注釈。

この例に示すQueueSampler MXBeanは、MXBeanの導入に示したMXBeanの例と基本的に同じアクションを実行していますが、MBean記述子が追加されている点が異なります。この例は、DescriptorKeyメタ注釈を使用することで、標準MBean (またはMXBean)インタフェース内の注釈によって標準MBean (またはMXBean)の記述子に新しい記述子を追加する方法を示しています。

DescriptorKey注釈

新しい注釈、DescriptorKey、を使用することで、標準MBeanまたはMXBeanインタフェース内の注釈によって標準MBeanまたはMXBeanの記述子に情報を追加できます。これによって、ツールで既存の管理モデルから標準MBeanを生成し、そのモデルからの情報を別のファイルではなく生成されたMBeanインタフェースに含めることができます。コード例2-9 Author注釈は、Author注釈の定義を示しています。

コード例2-9 Author注釈

 
package com.example.mxbeans; 
 
import java.lang.annotation.Documented; 
import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 
import javax.management.DescriptorKey; 
 
@Documented 
@Target(ElementType.TYPE) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface Author { 
    @DescriptorKey("author") 
    String value(); 
} 

この注釈は、MBeanインタフェースの作成者の名前を提供します。新しいフィールドauthorは、@Author注釈によって定義された値を持つMBeanInfo記述子に追加されます。ファイルVersionおよびDisplayNameは、これらの名前の注釈を、前述のAuthorの場合とまったく同様に定義します。VersionおよびDisplayName@DescriptorKey値は、それぞれ“version”および“displayname”です。

Versionの場合、新しいフィールドversion@Version注釈によって定義された値を持つMBeanInfo記述子に追加されます。

DisplayNameの場合、新しいフィールドdisplayNameは、注釈を付けられたメソッドが取得メソッド/設定メソッドと操作のどちらであるかに応じて、それぞれ@DisplayName注釈によって定義された値を持つMBeanAttributeInfo記述子またはMBeanOperationInfo記述子に追加されます。

MBean記述子の使用

次の例で使用されているQueueSamplerMXBeanインタフェースは、MBean記述子を実装してその情報の一部を公開する範囲にかぎり、MXBeanの例で使用されているインタフェースとはわずかに異なります。

コード例2-10 記述子を使用したQueueSamplerMXBean

 
package com.example.mxbeans; 
 
@Author("Mr Bean") 
@Version("1.0") 
public interface QueueSamplerMXBean { 
    @DisplayName("GETTER: QueueSample") 
    public QueueSample getQueueSample(); 
    @DisplayName("OPERATION: clearQueue") 
    public void clearQueue(); 
} 
 

これで@Author注釈はMr. Bean@Version注釈は1.0@DisplayNameは属性QueueSampleと操作clearQueueのどちらかの名前に設定されます。

MBean記述子の例題の実行

例題を実行するには、次の手順を実行します。

  1. MBean記述子にあるソース・コードをwork_dir/jmx_examples/Descriptorsにコピーします。

  2. Javaクラスの例をコンパイルします。

    $ javac com/example/mxbeans/*.java
  3. Mainアプリケーションを起動します。

    $ java com.example.mxbeans.Main

    何かの発生を待機中のMainに関する確認が表示されます。

  4. 同じマシンの別の端末ウィンドウで、JConsoleを起動します。

    $ jconsole

    JConsoleツールが開き、接続可能な稼動中のJMXエージェントのリストが表示されます。

  5. 新規接続」ウィンドウのリストからcom.example.mxbeans.Mainを選択し、「接続」をクリックします。

    プラットフォームの現在のアクティビティのサマリーが表示されます。

  6. MBean」タブをクリックします。

    このパネルに、現在MBeanサーバーに登録されているすべてのMBeanが表示されます。

  7. 左フレームにあるMBeanツリーのcom.example.mxbeansノードを展開します。

    Mainで作成され、登録されたMBean QueueSamplerの例が表示されます。QueueSamplerをクリックすると、関連するAttributesおよびOperationsノードがMBeanツリーに表示されます。フィールドauthorおよびversionMBeanInfo記述子表に表示されます。

  8. QueueSampler MBeanノードの下にあるAttributesおよびOperationsノードを展開します。

    AttributesとOperationsが個別に表示されます。

  9. QueueSampleノードを選択します。

    MBeanAttributeInfo記述子表にdisplayNameフィールドが表示されます。

  10. clearQueueノードを選択します。

    MBeanOperationInfo記述子表にdisplayNameフィールドが表示されます。

  11. 接続」をクリックし、次に「終了」をクリックして、JConsoleを終了します。