今月でとうとうこの連載も1周年を迎えることができました。筆者にとってはじめての連載ということで,連載前は本当に書けるのだろうかとかなり心配したのですが,とりあえず1年間無事に続けることができました。

これもひとえに読者のみなさまのおかげです。これからも最新のJavaの情報をお届けできるようにしていきたいと思います。

というわけで,本題に入りましょう。

今週も,Java SE 6のソフトウエア管理に関する新機能です。

属性を監視するモニター

この連載でJMXを解説したときに,いくつか取りあげなかった機能があります。そのうちの一つがモニターです。

モニターは特殊なMBeanで,他のMBean/MXBeanの属性を定期的に調べることができます。それぞれにルールを設定でき,そのルールに応じてイベント(JMXの場合,ノティフィケーションといいます)を発生させることができます。

標準では3種類のモニターを使用できます。いずれもjavax.management.monitorパッケージで定義されており,javax.management.monitor.Monitorクラスの派生クラスになります。

表1 標準で提供されるモニター
クラス名 説明
CounterMonitor 数値を監視するモニター
しきい値を超えるとノティフィケーションを発生する
GaugeMonitor 数値を監視するモニター
上限と下限の二つのしきい値を設定できる
StringMonitor 文字列を監視するモニター

CounterMonitorクラスとGaugeMonitorクラスは数値を監視するためのモニターです。もう一つのStringMonitorクラスは文字列を監視します。

CounterMonitorは,図1に示したように,設定したしきい値を超えるとノティフィケーションを発生させるモニターです。オフセットを指定しておくと,しきい値を超えたあとオフセット分だけ値が増加したときにノティフィケーションを発生します。例えば,しきい値を5,オフセットを3に指定した場合,モニターする値が5,8,11...のときにノティフィケーションが発生します。

また,カウントをリセットするには,モジュラスというプロパティを指定しておきます。カウンタがモジュラスで指定した値になったとき,0にリセットされます。

GaugeMonitorクラスは図2に示したように,上限と下限を設定できるモニターです。上限を超えるか,下限を下回ったときにノティフィケーションが発生します。

最後のStringMonitorは監視する対象が文字列になります。監視対象の文字列が設定された文字列と同じになったときノティフィケーションを発生させるモードと,異なったときにノティフィケーションを発生させるモードがあります。

CounterMonitor
図1 CounterMonitor
GaugeMonitor
図2 GaugeMonitor

モニターを使ってみる

モニターを理解するには使ってみるのが一番です。ここでは第7回「自分で作るMXBean」で使用したサンプルにCounterMonitorクラスを追加してみましょう。

サンプルはここからダウンロードできます:Counter.javaCounterWatcher.javaCounterWatcherImpl.java

コードを変更するのはCoungterWatcherImpleクラスだけです。mainメソッドでMXBeanを作成しているので,そこでCounterMonitorクラスも設定します。

private static final String MONITOR_NAME
        = "net.javainthebox.counter:type=CounterMonitor";

public static void main(String[] args) {
    Counter counter = new Counter();
    CounterWatcher watcher = new CounterWatcherImpl(counter);

    try {
        MBeanServer server = ManagementFactory.getPlatformMBeanServer();
        ObjectName name = new ObjectName(NAME);
        server.registerMBean(watcher, name);

        // 1. カウンタ・モニターを生成し,MBeanServerに登録
        CounterMonitor counterMonitor = new CounterMonitor();
        ObjectName monitorName = new ObjectName(MONITOR_NAME);
        server.registerMBean(counterMonitor, monitorName);

        // 2. カウンタ・モニターにcounterのcountを登録
        counterMonitor.addObservedObject(name);
        counterMonitor.setObservedAttribute("Count");

        // 3. ノティフィケーションを発生可能に設定
        counterMonitor.setNotify(true);

        // 4. 初期しきい値を3に設定
        counterMonitor.setInitThreshold(3);

        // 5. オフセットを2に設定
        counterMonitor.setOffset(2);

        // 6. モジュラスを10に設定
        counterMonitor.setModulus(10);

        // 7. ポーリングの時間を100msに設定
        counterMonitor.setGranularityPeriod(100L);

        // 8. モニターの開始
        counterMonitor.start();

    } catch (MalformedObjectNameException ex) {
        ex.printStackTrace();
    } catch (InstanceAlreadyExistsException ex) {
        ex.printStackTrace();
    } catch (MBeanRegistrationException ex) {
        ex.printStackTrace();
    } catch (NotCompliantMBeanException ex) {
        ex.printStackTrace();
    }
}

CounterMonitorクラスは,単純にnewで生成できます。CounterMonitorクラスもMBeanなので,MBeanServerオブジェクトへの登録は他のMBean/MXBeanと同様です。

2.で監視するMBean/MXBeanをaddObservedObjectメソッドで指定し,setObservedAttributeメソッドを使用して属性を指定します。しきい値などのプロパティを設定しているのが,3.から7.のステップです。

最後にstartメソッドでCounterMonitorオブジェクトを起動します。

さっそく起動して,jconsoleで確かめてみましょう。

MBeanタブでMBeanの一覧を見てみると,CounterMonitorがあることを確認できます。図3はCounterMonitorのノティフィケーションに関するビューを示しています。MBeanからのノティフィケーションを受け取るには,[登録]ボタンをクリックします。

CounterMonitorのしきい値は3に設定したので,カウンタが3になるとノティフィケーションが発生します(図4)。オフセットは2に設定したので,カウンタが3,5,7,9でノティフィケーションが発生します。

CounterMonitorの内部カウンタは一律に増加するだけで,減少することはありません。内部カウンタをリセットさせるには,モジュラスを設定しておきます。内部カウンタがモジュラスに到達すると,0にリセットされます。

このサンプルではモジュラスを10にしてあります。このため,カウンタが10まで到達し,リセットされると,CounterMonitorも再びノティフィケーションを発生します(図5)。

CounterMonitorのノティフィケーション
図3 CounterMonitorのノティフィケーション
ノティフィケーションの通知
図4 ノティフィケーションの通知
ノティフィケーションの通知
図5 ノティフィケーションの通知

オフセットもモジュラスも設定しない場合は,しきい値に達すると常にノティフィケーションを発生するようになります。

MBean/MXBeanにノティフィケーションを発生させる機能を実装しなくても,このようにモニターを使うことでノティフィケーションを発生させることができます。

しかし,いくつかの制約もあります。制約の一つは,複合要素の属性に対するモニターができないことです。

例えば,MemoryMXBeanのヒープ使用量を監視したいとします。ヒープ使用量はMemoryMXBeanが直接保持せず,MemoryUsageクラスのused属性として保持されています。このような場合,モニターはMemoryUsageクラスにアクセスする手段を持たないため,監視できませんでした。

Java SE 6ではこの制約が取り払われました。複合要素でも監視が可能になったのです。

複合要素の監視

モニターで属性を監視するには,前述したようにMonitor#setObservedAttributeメソッドで指定します。CounterWatcherImplクラスでは次のように記述しました。

counterMonitor.setObservedAttribute("Count");

CounterWatcherのCount属性を表しています。つまり,この値を取得するには,getCountメソッドを使用します。

複合要素の場合,次のように記述します。

counterMonitor.setObservedAttribute("HeapMemoryUsage.used");

この記述はMemoryMXBeanのHeapMemoryUsage属性のused属性を示しています。つまり,複合要素の場合は「.」(ピリオド)で続けて属性を記述するようにします。

この場合,MemoryMXBeanのgetHeapMemoryUsageメソッドがコールされ,その次にMemoryUsage#getUsedメソッドがコールされます。

ModelMBeanで使用されるCompositeDataクラスを使用して複数の属性を保持するときには,ピリオドの後の文字列をCompositeData#getメソッドの引数にしてコールします。

また,xxx属性のyyy属性のzzz属性のような場合には,同じくピリオドで区切ってxxx.yyy.zzzと記述します。

このように複合要素の場合でも,特別なメソッドを必要とせず,普通の属性を監視するのと全く同じ方法で監視できるのです。

著者紹介 櫻庭祐一

横河電機 ネットワーク開発センタ所属。Java in the Box 主筆

今月の櫻庭

この時期になると何となく気になるのが,クリスマス。

実をいうと,櫻庭はクリスマスCDのコレクターなのです。数えたことがないので正確な枚数はわからないのですが,優に100枚はあるはず。

今年もDaryl Hall & John OatsやAimee Mannなどのクリスマスアルバムが発売されています。ということで,今年のクリスマスアルバムの櫻庭のお薦めは...

  • 癒されたいあなたには
    Keali'i Reichel "Maluhia"
  • しっとりとしたクリスマスを過したいあなたには
    Sara McLachlan "Wintersong"
  • ちょっと変ったのが好みというあなたには
    Bootsy Collins "Christmas Is 4 Ever"

いかがですか。なお,これを書いている時点では,James TaylorやBlackmore's Nightなど,聴いていないアルバムもあるので,お薦めが入れ替わる可能性はありますが,参考になればと思います。