Standard MBean
体重計やレントゲンに相当するStabdard MBean
Dynamic MBean
血液検査に相当するDynamic MBean

さて,今週から実際にMBeanを作っていきましょう。

MBeanの種類には大別すると,Standard MBeanとDyanamic MBeanがあります(先月の記事を参考にしてください)。

Standard MBeanは,管理情報の取得や操作のためのインタフェースとクラスを作成する必要があります。仕組みは簡単なのですが,管理情報を追加したい時はインタフェースとクラスを書き換える必要があります。

これに対して,Dynamic MBeanは管理情報の取得・操作を行うクラスを動的に生成します。このため,管理情報を追加したいときでも,設定を変更するだけで済みます。

たとえてみると,Standard MBeanは体重計やレントゲン,Dynamic MBeanは血液検査に相当します。

体重計は体重を測るという用途に特化されています。体重計で体脂肪を測れるようにするには,体重計自体の変更を行わなければなりません(普通は,体脂肪測定機能が付いた新しい体重計を買いますね)。

血液検査にはコレステロールなど様々な測定項目があり,そこから検査の時に何を測定するかを指定します。すでに,それぞれの測定項目に対応する検査機器は用意されているので,それらの中から使うものを選ぶという感じでしょうか。

さて,今週は体重計のほう,つまりStandard MBeanを作成していきます。

Standard MBeanの作成

Standard MBeanは前述したようにインタフェースとクラスから構成されます。

まずはMBeanのインタフェースを作成しましょう。Standard MBeanを表すインタフェースには,名前の最後にMBeanを付けるという命名規則があります。

今回はDispatcher1クラスに対応するMBeanなので,DispatcherInfoMBeanという名前にしてみました。

public interface DispatcherInfoMBean {
    public int getPageCount();
    public void resetPageCount();
}

DispatcherInfoMBeanインタフェースで定義しているのは,ページ・カウントを取得するためのgetPageCountメソッドと,ページ・カウントをリセットするためのresetPageCountメソッドです。

このメソッド,どこかで見たことのあるような感じがしませんか。そうです,先週説明したDispatcher1クラスに変更した部分に対応しています(先週の記事)。

このインタフェースを実装するクラスを作りましょう。クラス名はMBeanのインタフェース名からMBeanを取りのぞいたものにします。

public class DispatcherInfo
                    implements DispatcherInfoMBean{
    private Dispatcher1 dispatcher;
 
    public DispatcherInfo(Dispatcher1 dispatcher) {
        this.dispatcher = dispatcher;
    }
 
    public int getPageCount() {
        return dispatcher.getPageCount();
    }
 
    public void resetPageCount() {
        dispatcher.resetPageCount();
    }
}

DispatcherInfoクラスは「フィールドにDispatcher1オブジェクトを保持し,それぞれのメソッドはDispatcher1オブジェクトをコールする」というだけの簡単なクラスです。

MBeanServerの作成とMBeanの登録

MBeanを定義できたので,MBeanを生成し,MBeanServerに登録する処理を記述しましょう。

MBeanの本体であるDispatcherInfoクラスはDispatcher1クラスに対応するので,Dispatcher1オブジェクトが生成されるときにDispatcherInfoオブジェクトを生成することにします。

Dispatcher1オブジェクトの生成はN1クラスで行っています。該当個所を以下に示します。

void runServer() throws Exception {
    Dispatcher d = new Dispatcher1();
    d.register(ssc, SelectionKey.OP_ACCEPT,
               new AcceptHandler(ssc, d, sslContext));
    d.run();
}

このrunServerメソッドにMBeanの生成,およびMBeanServerへの登録処理を加えました(赤字が変更箇所)。なお,例外処理は省略しました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private static final String DISPATCHER_NAME
                            = "sample:name=dispatcher";
 
void runServer() throws Exception {
    Dispatcher1 d = new Dispatcher1();
 
    // MBeanを作成
    DispatcherInfo info = new DispatcherInfo(d);
    ObjectName name = new ObjectName(DISPATCHER_NAME);
 
    // MBeanServerがすでに生成されていれば,それを使用する
    // なければ新しく生成
    MBeanServer server;
    List servers 
         = MBeanServerFactory.findMBeanServer(null);
    if (servers.size() > 0) {
        server = (MBeanServer)servers.get(0);
    } else {
        server = MBeanServerFactory.createMBeanServer();
    }
        
    // MBeanを登録
    server.registerMBean(info, name);

    d.register(ssc, SelectionKey.OP_ACCEPT,
               new AcceptHandler(ssc, d, sslContext));
    d.run();
}

8~9行目がMBeanの生成を行っている部分です。

MBeanの生成は普通のオブジェクト生成と変わりありません。異なるのはMBeanには名前があるということです。MBeanの名前を表すにはjavax.management.ObjectNameクラスを使用します。

MBeanの名前で必須なのはドメインです。ドメインは,パッケージに相当するMBeanの名前空間を示しており,実際にパッケージ名を使うことも多くあります。ここでは,サンプルなのでsampleというドメインを使用しました。

名前は[ドメイン名:属性名=属性値]と記述します。属性にはnameなどがありますが,MBeanによって記述できる属性は異なります。属性が複数ある場合は,カンマで区切って指定するようにします。

ここではnameを"dispatcher"としました。

次はMBeanServerオブジェクトの生成です。13行目から20行目が対応する部分です。

一つのシステムの中に複数のMBeanServerオブジェクトを生成することは可能です。しかし,ここではすでにMBeanServerオブジェクトが存在していればそれを使用し,なければ生成するようにしました。

すでにMBeanServerオブジェクトが存在するかどうかを調べるにはjavax.management.MBeanServerFactoryクラスのfindMBeanServerメソッドを使用します。引数がnullの場合はすべてのMBeanServerオブジェクトを返します。

findMBeanServerメソッドの戻り値はListオブジェクトなので,空でなければ先頭にあるMBeanServerオブジェクトを利用します。

もし,MBeanServerオブジェクトがなければ,MBeanServerFactoryクラスのcreateMBeanServerメソッドを使用して,MBeanServerオブジェクトを生成します。

最後にMBeanServerオブジェクトにMBeanを登録します(23行目)。registerMBeanメソッドは第1引数がMBeanオブジェクト,第2引数がObjectNameオブジェクト(つまりMBeanの名前)です。

このサンプルでは,外部の管理ツールからアクセスするためのConnectorもしくはProtocol Adapterに関しては何も設定していません。

J2SE 5.0では,起動時オプションでMXBeanを参照できるように指定すると,Connectorが自動的に生成されます。自動的に生成されたConnectorを使用することで,コードに記述しなくても外部の管理ツールからMXBeanにアクセスできます。

著者紹介 櫻庭祐一

横河電機の研究部門に勤務。同氏のJavaプログラマ向け情報ページ「Java in the Box」はあまりに有名