Health Center API を使用して Java アプリケーションの監視を行う、第 1 回

Health Center API を使い始める

Health Center の 2.1 リリースには強力な API が含まれています。Java 開発者は、この API を使用することにより、作成する Java アプリケーションに Health Center を組み込んで、その監視機能を活用して問題のトラブルシューティングをすることができます。この記事は全 2 回からなる連載の第 1 回として、Health Center API を使用する方法と、実行中の Java アプリケーションがデッドロックしていないかどうかを監視するためにこの API を使用する方法について説明します。第 2 回では、今回の記事で作成するデッドロック検出アプリケーションを使用して、メソッドのプロファイル・ビューを追加し、アプリケーションのどの部分が CPU サイクルを最も消費しているかを示す方法について説明します。

Toby Corbin, Software Engineer, IBM  

Toby CorbinToby Corbin は Health Center 監視ツールの中心的開発者です。彼は他にも、コンシューマビリティー・ツールを IBM Java Technology Centre で開発しています。彼は 2001年に IBM に入社して 4 年間、Java ランタイム環境の各国語サポートやグローバル化に携わってきました。また彼は Swing ライブラリーと AWT ライブラリーを 2 年にわたって開発しました。



2013年 6月 06日

皆さんはこれまでに、明らかな理由もないのにアプリケーション・サーバーがハングアップしたり、Java アプリケーションが応答しなくなったりした経験がおありでしょうか?あるいは、アプリケーションのメモリーが足りなくなったり、アプリケーションの動作が遅くなったりしていないでしょうか? Health Center を使用すると、そうした問題のトラブルシューティングを容易に行うことができます。

Health Center を使用して問題の監視と診断を行う

IBM Monitoring and Diagnostics Tools for Java - Health Center (Health Center) は、IBM JVM (Java Virtual Machine) 上で実行されるアプリケーションを監視するための、オーバーヘッドの少ない無料診断ツールおよび API です。Health Center を利用すると、問題を特定するための情報や、問題の解決を支援するための情報が得られるため、実行中の Java アプリケーションの状態を即座に判断することができます。Health Center により、以下のことが可能になります。

  • ネイティブ・メモリーまたはヒープ・メモリーがリークしていないかどうかを明らかにする
  • 実行に最も時間がかかっているメソッドを調べる
  • I/O のボトルネックを特定する
  • ガーベッジ・コレクションを視覚化し、調整する
  • ロックの競合を表示する
  • 通常とは異なる WebSphere Real Time イベントを分析する
  • アプリケーションのスレッド・アクティビティーを監視する
  • デッドロック状態を検出する
  • クラスのヒストグラム・データを収集する

Health Center の最新リリースは、新しくて強力な API として提供されています。この API を利用すると、独自の監視ツールを作成することができ、厄介で見つけにくい問題で悩むことはほとんどなくなります。

この記事では、アプリケーションがデッドロック状態に陥っていないかどうかを確認するための監視ツールの作成方法を学びます。また、そこで説明した原則を応用することにより、さらに詳細まで調べるツールを作成し、ガーベッジ・コレクションのアクティビティーからメソッドのプロファイルに至るまであらゆる情報を照会し、アプリケーションがどこで CPU サイクルを消費しているかを明らかにします。

システム要件

Health Center API バンドルには、少なくとも Eclipse 3.4 または Eclipse 4.x が必要です。

Health Center API パッケージを Eclipse にインストールする

IBM Monitoring and Diagnostics Tools は通常、ISA (IBM Support Assistant) にインストールされます。皆さんのアプリケーションに Health Center を組み込み、Health Center API を使用するアプリケーションをコーディングするには、まず Health Center を Eclipse 環境にインストールします。そのためには以下のステップに従います。

  1. Eclipse 開発環境を起動します。
  2. 「Help (ヘルプ)」 -> 「Install New Software (新規ソフトウェアのインストール」の順に選択します。
  3. ISA アップデート・サイトを新しいサイトとして追加します。
    1. 「Add (追加)」をクリックします。
    2. 「Name (名前)」ボックスに「ISA Update site」と入力します。
    3. 「Location (ロケーション)」ボックスには URL として「http://public.dhe.ibm.com/software/isa/isa410/production/」と入力します。この操作により、利用可能なすべてのツールの検索が数分かけて行われます。
  4. 検索ボックスに「Health Center」と入力します。
  5. 「Health Center Core Feature (Health Center コア・フィーチャー)」というパッケージを選択し、「Next (次へ)」をクリックします (図 1)。
    図 1. インストール可能なソフトウェアの一覧
    インストール可能なソフトウェアの一覧を表示する画面のスクリーン・キャプチャー
  6. インストール詳細を確認し、「Next (次へ)」をクリックします。
  7. ご使用条件を読んで、同意を選択したら、「Finish (完了)」をクリックします。これらのステップにより、Health Center のコア・フィーチャーが Eclipse IDE にインストールされます。これで、Health Center API を使用するアプリケーションをコーディングする準備が整いました。
  8. インストール詳細を確認し、「Next (次へ)」をクリックします。

この API を使用して、デッドロックを検出するための単純な RCP (Rich Client Platform: リッチ・クライアント・プラットフォーム) を作成します。まず、新しいプラグイン・プロジェクトを Eclipse で作成し、依存関係として Health Center API を追加します。そのためには以下のステップに従います。

  1. 「File (ファイル)」 -> 「New (新規)」 -> 「Project (プロジェクト)」 -> 「Plug-in Project (プラグイン・プロジェクト) 」の順に選択します。
  2. このプロジェクトに名前を付け (例えば、「HC_Deadlock」など)、「Next (次へ)」をクリックします。
  3. 「Generate an activator (アクティベーターを生成)」チェックボックスのチェックを外します。リッチ・クライアント・アプリケーションを作成するかどうかの質問には「Yes (はい)」をクリックし、「Next (次へ)」をクリックします。
    図 2. プラグイン・プロジェクトのオプション
    プラグイン・プロジェクトのオプションを表示する画面のスクリーン・キャプチャー
  4. 「Next (次へ)」をクリックします。テンプレート画面では、「Headless Hello RCP (ヘッドレス Hello RCP)」を選択し、「Finish (完了)」) をクリックします。

次に、この新しいプロジェクトの依存関係として Health Center API パッケージを追加します。そのためには以下のステップに従います。

  1. この API のインポートをマニフェストに追加するために、新しいプロジェクトの「META-INF」の下にある「MANIFEST.MF」ファイルを開きます (図 3)。
    図 3. 「Package Explorer (パッケージ・エクスプローラー)」に表示されたプラグイン
    「Package Explorer (パッケージ・エクスプローラー)」に表示されたプラグインのスクリーン・キャプチャー
  2. 「Dependencies (依存関係)」タブを選択し、「Add (追加)」をクリックします。「Select a Plug-in (プラグインを選択してください)」フィールドに検索対象として「healthcenter.api」と入力します。「com.ibm.java.diagnostics.healthcenter.api」プラグインを選択します。バージョン番号が図 4 とは異なる場合があることに注意してください (図 4)。
    図 4. Health Center API プラグインの選択
    Health Center API プラグインを選択する画面のスクリーン・キャプチャー
  3. 「OK」をクリックします。上記の「Dependencies (依存関係)」タブを選択するステップを繰り返し、今度は「org.eclipse.ui」を追加します。この場合もバージョン番号が図 5 とは異なる場合があることに注意してください (図 5)。
    図 5. org.eclipse.ui プラグインの選択
    org.eclipse.ui プラグインを選択する画面のスクリーン・キャプチャー
  4. 「OK」をクリックし、このファイルを保存します。

これで Health Center API プラグインが皆さんのアプリケーションに組み込まれ、このアプリケーションのコーディングを開始することができます。


デッドロック状態のアプリケーションをテストする

デッドロックを監視するツールを作成する前に、監視対象となるものが必要です。リスト 1 はデッドロック状態に陥る単純なアプリケーションのソース・コードです。

リスト 1. デッドロック状態に陥る単純なアプリケーション
public class GenerateDeadlock {
   AThread t1 = null;
   AThread t2 = null;
   AThread t3 = null;

   static class AThread extends Thread {
      Object hold;
      Object grab;

      AThread(String name, Object hold, Object grab) {
         super(name);
         this.hold = hold;
         this.grab = grab;
      }

      private void delay(long time) {
         try {
            Thread.sleep(time);
         } catch (InterruptedException e) {
         }
      }

      private void grabLocks() {
         System.out.println("Thread " + this + " about to hold " + hold);
         synchronized (hold) {
            System.out.println("  Thread " + this + " about to grab "
                  + grab);
            delay(5000);
            synchronized (grab) {
               System.out.println("    Thread " + this
                     + " got both monitors");
               delay(1000000);
            }
         }
      }

      public void run() {
         System.out.println("Thread " + this + " starting");
         for (int i = 0; i < 200000; i++) {
            grabLocks();
         }
         System.out.println("Thread " + this + " completed");
      }
   }

   private void createDeadlock() {
      System.out.println("Force 3 thread deadlock");
      String s1 = "obj 1";
      String s2 = "obj 2";
      String s3 = "obj 3";
      t1 = new AThread("Thread 1", s1, s2);
      t2 = new AThread("Thread 2", s2, s3);
      t3 = new AThread("Thread 3", s3, s1);
      t1.start();
      t2.start();
      t3.start();
   }

   public static void main(String[] args) {
      GenerateDeadlock d = new GenerateDeadlock();
      d.createDeadlock();
      try {
         Thread.sleep(1000);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
      System.out.println("Press a key to exit");
      try {
         System.in.read();
         System.exit(0);
      } catch (java.io.IOException e) {
      }
   }
}

Health Center は 2 つの部分で構成されます。その 1 つは「Health Center エージェント」であり、Health Center エージェントは監視対象となるアプリケーションと共にロードされます。このエージェントによって JVM 内のデータにアクセスすることができ、そのデータを、Health Center のもう 1 つの部分である「Health Center クライアント」が使用します。Health Center API を使用すると、この Health Center クライアント (通常は ISA から起動されます) にアクセスすることができます。Health Center エージェントによって起動されたアプリケーションに接続するために、皆さんのアプリケーションに Health Center クライアントを組み込んで、Health Center クライアントが監視および表示の対象とするすべてのデータにアクセスしてください。Health Center API には GUI はありませんが、その代わり、Health Center API によって得られるデータのすべてを皆さんのアプリケーションで使用することができます。図 6 は、Health Center クライアント (Health center client) と Health Center エージェント (Health center agent) が ISA と JVM (IBM JVM) にインストールされる場合の配置の概略を示しています。

図 6. Health Center クライアントと Health Center エージェントが ISA と JVM にインストールされる場合の配置
ISA と JVM における Health Center クライアントと Health Center エージェントの配置を示す図

リスト 1 のプログラムを、このプログラムに接続されている Health Center エージェントとともに起動します。また Health Center エージェントには、少なくとも Java 5 SR8、Java 6 SR1、Java 7 のいずれかの IBM Java が必要です。IBM Java は、IBM developer kits からダウンロードすることができます。

Java 5 SR10 以降、Java 6 SR5 以降、または Java 7 を使用する Health Center エージェントで監視対象のアプリケーションを起動するには、以下のコマンドを実行します (図 7)。

java - Xhealthcenter GenerateDeadlock

Java 5 SR9 またはそれより前のバージョン、Java 6 SR4 またはそれより前のバージョンのいずれかを使用する Health Center エージェントで起動する場合には、以下のコマンドを実行します

java - agentlib:healthcenter - Xtrace:output=healthcenter.out GenerateDeadlock
図 7. GenerateDeadlock プログラムを実行する
GenerateDeadlock プログラムを実行しているコマンドライン・ウィンドウのスクリーン・キャプチャー

Java 5 SR9 と Java 6 SR3 からは Health Center エージェントが自動的に組み込まれるようになっています。Health Center エージェントの最新バージョンと更新方法の手順については、Health Center のインフォメーション・センターで「Health Center エージェントのインストール」をご覧ください。


デッドロックを監視するアプリケーションをコーディングする

これで、基本的な Hello RCP World アプリケーションを変更し、Health Center API を使用するデッドロック検出ツールにする準備ができました。「Application.java」というファイルを開きます (図 8)。

図 8. Application.java コードの場所
Application.java コードの場所を示すスクリーン・キャプチャー

接続の詳細を設定する

まず、接続先のアプリケーションの詳細情報を持つ ConnectionProperties オブジェクトを取得します。このオブジェクトのデフォルトは localhost とポート 1972 を使用する設定になっていますが、これらの値はコンストラクター・メソッドやクラス・メソッドで変更すること (そして、セキュリティーを追加すること) ができます。

ConnectionProperties hcConn = new ConnectionProperties();

ConnectionProperties オブジェクトを取得したら、Health Center エージェントによって既に起動済みの監視対象アプリケーションに接続します。そして静的メソッド HealthCenterFactory.connect(hcConn, true) を呼び出すと、HealthCenter オブジェクトが返されます。このオブジェクトは Health Center に直接接続し、Health Center が監視しているすべてのデータにアクセスできるようになります。connect メソッドを呼び出すことによって皆さんのアプリケーションの中で Health Center のインスタンスが起動され、データの収集が開始されます。

HealthCenter hcMon = HealthCenterFactory.connect(hcConn,true);

データにアクセスする

前のセクションの手順で返された HealthCenter オブジェクトを使用すると、データを照会することができます。Health Center API の設計は GUI と似ています。HealthCenter オブジェクトを取得した後の最初のステップは、対象とするデータのタイプにアクセスすることです。この例ではデッドロックについて調べたいので、対象データは ThreadsData クラスの一部です。以下のようにして HealthCenter オブジェクトの getThreadsData() メソッドにアクセスすることができます。

ThreadsData hcThreadsData = HealthCenter.getThreadsData();

ThreadsData クラスには deadlockDetected() メソッドがあり、このメソッドはデッドロックが検出されると true を返します。このメソッドを以下のようにしてポーリングすると、デッドロックが発生した場合に通知されます。

if(hcThreadsData.deadlockDetected()) {
      do something
}

分析推奨エンジンにアクセスする

Health Center には推奨エンジンが組み込まれており、このエンジンがあらゆる分析を行って分析結果を返します。通常、Health Center の完全版を実行すると、「Analysis and Recommendations (分析および推奨事項)」パネルに以下のような内容が表示されます (図 9)。

図 9. Health Center の「Analysis and Recommendations (分析および推奨事項)」パネル
Health Center の「Analysis and Recommendations (分析および推奨事項)」パネルのスクリーン・キャプチャー

推奨事項を照会するには、いくつかのメソッドを使用することができます。getAllRecommendations() はすべての推奨事項の配列を返しますが、getCriticalRecommendations() を呼び出せば、クリティカルな問題のみを照会することができます。getCriticalRecommendations()ThreadsData オブジェクトのメソッドです。

String[] hcThreadsRec = hcThreadsData.getCriticalRecommendations()

ソース・コード全体を見る

上記の 5 つの呼び出しは、皆さんのアプリケーションに Health Center を組み込むために、また監視対象のアプリケーションにデッドロックがないかどうかを調べるために必要なものです。リスト 2 に、ここで使用した 5 つの呼び出しのソース・コード全体を示します。

リスト 2. ここで使用した 5 つの呼び出しのソース・コード全体
package deadlockdemo;

import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;

import com.ibm.java.diagnostics.healthcenter.api.ConnectionProperties;
import com.ibm.java.diagnostics.healthcenter.api.HealthCenter;
import com.ibm.java.diagnostics.healthcenter.api.factory.HealthCenterFactory;
import com.ibm.java.diagnostics.healthcenter.api.threads.ThreadsData;

/**
 * This class controls all aspects of the application's execution
 */
public class Application implements IApplication {
   HealthCenter hcMon;

   public Object start(IApplicationContext context) throws Exception {
      ConnectionProperties hcConn = new ConnectionProperties();
      hcMon = HealthCenterFactory.connect(hcConn, true);
      try {
         System.out
               .println("Waiting for 10 seconds to allow initial data to be
                        parsed from the connection");
         Thread.sleep(10000);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
      checkForDeadlock();
      return IApplication.EXIT_OK;
   }

   public void stop() {
      // nothing to do
   }

   public void checkForDeadlock() {
      while (!detectDeadlock()) {
         try {
            Thread.sleep(5000);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }

   private boolean detectDeadlock() {
      ThreadsData hcthreadsData = hcMon.getThreadsData();
      if (hcthreadsData == null) {
         System.out.println("No threads yet");
      } else {
         if (hcthreadsData.deadlockDetected()) {
            Display display = new Display();
            Shell shell = new Shell(display);

            MessageBox mb = new MessageBox(shell);
            String deadlockMessage = new String();
            String[] hcThreadsRec = hcthreadsData
                  .getCriticalRecommendations();
            for (String rec : hcThreadsRec) {
               deadlockMessage = deadlockMessage + rec + "\n";
            }
            mb.setMessage(deadlockMessage);
            mb.setText("Deadlock detected");
            mb.open();
            display.dispose();
            return true;
         }
      }
      return false;
   }
}

デッドロックを監視する

これで、デッドロックを監視するアプリケーションと、バックグラウンドで実行されてデッドロック状態に陥るプログラムが用意できました。いくつかのメッセージによって、デッドロック状態であることが示されています (図 10)。

図 10. 「Deadlock detected (デッドロック検出)」結果パネル
「Deadlock detected (デッドロック検出)」結果パネルのスクリーン・キャプチャー

まとめ

この記事では、Health Center API を使い始める方法と、アプリケーションがデッドロック状態になっていないかを調べる監視ツールを作成する方法について、基本的な事項を説明しました。この記事で説明した方法を応用することで、Health Center 内部にある任意のデータを抽出し、利用することができます。第 2 回では、今回の記事で説明した概念を基にして、アプリケーションのどの部分が CPU サイクルを最も消費しているかを示すために、デッドロック検出アプリケーションにメソッドのプロファイル・ビューを追加します。

参考文献

学ぶために

製品や技術を入手するために

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Java technology
ArticleID=932156
ArticleTitle=Health Center API を使用して Java アプリケーションの監視を行う、第 1 回
publish-date=06062013