JMX テクノロジを使用する監視と管理
Java 仮想マシン (Java VM) は組み込みインストゥルメンテーションを備え、これによって Java Management Extensions (JMX) テクノロジを使用した監視と管理を行うことができます。これらの組み込み管理ユーティリティーは通常、Java VM の「アウトオブボックスの管理」ツールと呼ばれます。適切に計測されたアプリケーションであれば、JMX API を使用して監視できます。
システムプロパティーの設定
アウトオブボックスの JMX エージェントを有効にして、Java VM の監視と管理ができるように設定するには、Java VM の起動時に特定のシステムプロパティーを設定する必要があります。システムプロパティーは、コマンド行で次のように設定します。
java -Dproperty=value ... |
このようにシステムプロパティーはいくつでも設定できます。管理プロパティーは、値を指定しないとデフォルト値に設定されます。アウトオブボックスの管理プロパティーのフルセットについては、本章の末尾の表 2-1 を参照してください。システムプロパティーは、「アウトオブボックスの監視および管理のプロパティー」で説明しているように、構成ファイルの中でも設定できます。
注 - コマンド行から Java VM を起動するには、パスに JRE_HOME/bin を追加する必要があります。JRE_HOME は Java Runtime Environment (JRE) 実装が入ったディレクトリです。別の方法として、コマンド入力時にフルパスをキー入力しても構いません。
Java HotSpot VM でサポートされる構文とコマンド行のフルセットオプションについては、次のドキュメントを参照してください。
アウトオブボックスの管理の有効化
JMX API を使用して Java プラットフォームを監視するには、次の手順を実行する必要があります。
Java VM の起動時に JMX エージェント (プラットフォーム MBean サーバーの別名) を有効にします。JMX エージェントの有効範囲は次のとおりです。
ローカル監視、ローカルシステムで実行されるクライアント管理アプリケーション。
リモート監視、リモートシステムで実行されるクライアント管理アプリケーション。
JMX 仕様にコンパイルするツール (JConsole など) で Java VM を監視します。コンソールの詳細については、第 3 章「JConsole の使用」 を参照してください。
それらのステップについて、次のセクションで説明します。
ローカルの監視および管理
Java SE プラットフォームの以前のリリースでは、JMX クライアントでローカルの Java VM にアクセスするには、Java VM または Java アプリケーションの起動時に、次のシステムプロパティーを設定する必要がありました。
com.sun.management.jmxremote |
このプロパティーを設定することで Java VM プラットフォームの MBean を登録し、非公開インタフェースを介して Remote Method Invocation (RMI) コネクタを公開して、JMX クライアントアプリケーションでローカルの Java プラットフォーム (JMX クライアントと同じマシン上で動作する Java VM) を監視できるようにしました。
Java SE 6 プラットフォームでは、このシステムプロパティーの設定は必要ありません。どのアプリケーションでも、Java SE 6 プラットフォームで起動したものであれば Attach API がサポートされ、ローカルの監視と管理が必要な場合は自動的に使用可能になります。
たとえば、以前なら Java SE のサンプルアプリケーション Notepad で JMX エージェントを有効にするには、次のコマンドを実行する必要がありました。
% cd JDK_HOME/demo/jfc/Notepad % java -Dcom.sun.management.jmxremote -jar Notepad.jar |
このコマンドのうち JDK_HOME は、 Java Development Kit (JDK) がインストールされるディレクトリです。Java SE 6 プラットフォームでは、次のコマンドを実行するだけで Notepad が起動します。
% java -jar Notepad.jar |
Notepad が起動すると、Attach API を使用する JMX クライアントがアウトオブボックスの管理エージェントを有効にし、Notepad アプリケーションの監視と管理が行えるようになります。
注 - Windows プラットフォームではセキュリティー上の理由から、ローカルの監視と管理がサポートされるのは、デフォルトの一時ディレクトリが、ファイルおよびディレクトリのアクセス権が設定可能なファイルシステム (たとえば、New Technology File System (NTFS) ファイルシステム) にある場合に限られます。アクセス制御が不十分な File Allocation Table (FAT) ファイルシステムではサポートされません。
JConsole を使用したローカルの管理および管理
JConsole を使用したローカルの監視は、開発とプロトタイプの作成に役立ちます。JConsole のローカルな使用は、実稼動環境ではお勧めしません。JConsole 自体が相当のシステムリソースを消費するためです。JConsole はリモートシステムで使用し、監視対象のプラットフォームから分離した方がよいでしょう。
それでもローカルの監視に JConsole を使用する場合は、コマンドシェルに jconsole とキー入力してツールを起動します。引数なしで jconsole を起動すると、ローカルの Java アプリケーションがすべて自動検出され、ダイアログボックスが表示されます。このダイアログボックスから、監視対象とするアプリケーションを選択します。JConsole とアプリケーションはどちらも、同じユーザーが実行する必要があります。システムの監視には、オペレーティングシステムのファイルアクセス権が必要になるためです。
注 - コマンド行から JConsole を起動するには、JDK_HOME/bin をパスに追加します。別の方法として、コマンド入力時にフルパスをキー入力しても構いません。
詳細は、第 3章「JConsole の使用」を参照してください。
リモートの監視および管理
リモートシステムから監視と管理を行うには、Java VM 起動時に次のシステムプロパティーを設定する必要があります。
com.sun.management.jmxremote.port=portNum |
このプロパティーの中の portNum は、JMX RMI 接続に使用するポート番号です。必ず未使用のポート番号を指定してください。ローカルアクセスでは RMI コネクタを公開するのに加えて、このプロパティーを設定することにより、標準名「jmxrmi」を使用して、指定されたポートの非公開の読み取り専用レジストリで追加の RMI コネクタを公開します。
注 - セキュリティー用に設定するプロパティーのほかに、前記のシステムプロパティーを設定する必要があります。これについては「パスワード認証の使用」以降の節を参照してください。
リモートの監視と管理には、権限のない人がアプリケーションの制御や監視ができないように、セキュリティーが必要です。デフォルトで、 SSL (secure sockets layer) 経由のパスワード認証と TLS (Transport Layer Security) が有効になっています。次の節に説明するように、パスワード認証と SSL は個別に無効にすることができます。
JMX エージェントをリモートで使用可能にすると、「JConsole によるリモート監視」に説明するように、JConsole でアプリケーションを監視できます。プログラムから管理エージェントに接続する方法については、「プログラムによる JMX エージェント への接続」を参照してください。
パスワード認証の使用
デフォルトでは、リモート監視で JMX エージェントを有効にすると、JMX エージェントはパスワード認証を使用します。ただし、パスワードを設定する方法は、シングルユーザー環境かマルチユーザー環境かによって異なります。
パスワードはパスワードファイルにクリアテキストで格納されるため、通常のユーザー名とパスワードを監視用に使用することはお勧めできません。代わりに、monitorRole および controlRole などのパスワードファイルで指定したユーザー名を使用します。詳細は、「パスワードとアクセスファイルの使用」 を参照してください。
シングルユーザー環境を設定する方法
JRE_HOME/lib/management ディレクトリのパスワードファイルを、次のように設定します。
パスワードテンプレートファイル jmxremote.password.template を jmxremote.password にコピーします。
ファイル所有者だけがパスワードファイルを読み書きできるように、ファイルのアクセス権を設定します。
monitorRole や controlRole などのロールのパスワードを追加します。
マルチユーザー環境を設定する方法
JRE_HOME/lib/management ディレクトリのパスワードファイルを、次のように設定します。
パスワードテンプレートファイル jmxremote.password.template をホームディレクトリにコピーし、そのファイル名を jmxremote.password に変更します。
ファイル所有者だけがパスワードファイルを読み書きできるように、ファイルのアクセス権を設定します。
monitorRole や controlRole などのロールのパスワードを追加します。
Java VM の起動時に、次のシステムプロパティーを設定します。
com.sun.management.jmxremote.password.file=pwFilePath
このプロパティーの中の pwFilePath は、パスワードファイルへのパスです。
警告 - クライアントがセキュリティー保護されていない RMI レジストリ (デフォルト) からリモートコネクタを取得すると、リモートコネクタからのパスワード認証でセキュリティーの問題が発生する可能性があります。ターゲットサーバー上で正当な RMI レジストリが起動する前に攻撃者が偽の RMI レジストリを起動すれば、クライアントのパスワードを盗むことができます。これは、システムプロパティー com.sun.management.jmxremote.port=portNum でリモート管理を有効にして Java VM を起動する場合も当てはまります。SSL が有効になっていても同じです。このような攻撃者は発見されることが多いものの、脆弱性があることは確かです。
この問題を避けるため、認証にはパスワードの代わりに SSL クライアント証明書を使用してください。または、クライアントがリモートコネクタオブジェクトを安全に (たとえばセキュリティー保護された LDAP サーバー、または共有のセキュリティー保護されたファイルシステムにあるファイルを経由して) 取得するようにしてください。
パスワード認証の無効化
リモート監視のパスワード認証は、デフォルトで有効になっています。パスワード認証を無効にするには、JVM の起動時に次のシステムプロパティーを正しく設定します。
com.sun.management.jmxremote.authenticate=false |
警告 - この構成は安全ではありません。JMX ポート番号およびホスト名を知っている (または推測する) リモートユーザーなら誰でも、Java アプリケーションおよびプラットフォームの監視と制御ができます。開発用には許容される場合があっても、実稼働システムにはお勧めしません。
パスワード認証を無効にする場合、「セキュリティーの無効化」で説明しているように SSL を無効にすることもできます。「SSL クライアント認証の有効化」で説明しているように、パスワードを無効にして SSL クライアント認証を使用する場合もあります。
SSL の使用
リモート監視および管理を有効にすると、SSL はデフォルトで有効になっています。SSL を使用するには、JMX エージェント (MBean サーバー) が稼動するシステム上でデジタル証明書を設定して、次に SSL を正しく設定する必要があります。コマンド行ユーティリティー keytool を使用して、証明書を操作します。一般的な手順は次のとおりです。
SSL を設定する方法
サーバー上でまだ鍵ペアと証明書を設定していない場合、次の手順に従います。
keytool -genkey コマンドで鍵ペアを生成します。
keytool -certreq コマンドで認証局 (CA) に署名付き証明書を要求します。
keytool -import コマンドで、証明書をキーストアにインポートします。keytool ドキュメントの「証明書のインポート」を参照してください。
詳細および例については、「keytool - 鍵および証明書管理ツール」(Solaris および Linux) または (Windows プラットフォーム)を参照してください。
サーバーシステム上で SSL を設定します。
このドキュメントでは、SSL の設定とカスタマイズについて詳細には説明しませんが、通常は次の表に記載されているシステムプロパティーを設定する必要があります。
システムプロパティー
説明
javax.net.ssl.keyStore
キーストアの場所。
javax.net.ssl.keyStoreType
デフォルトのキーストア型。
javax.net.ssl.keyStorePassword
デフォルトのキーストアパスワード。
javax.net.ssl.trustStore
トラストストアの場所。
javax.net.ssl.trustStoreType
デフォルトのトラストストア型。
javax.net.ssl.trustStorePassword
デフォルトのトラストストアパスワード。
システムプロパティーの設定の詳細は、前記の「システムプロパティーの設定」または次のドキュメントを参照してください。
RMI レジストリ認証の有効化
リモートアプリケーションの監視で接続を設定するとき、SSL で保護されているRMI レジストリに RMI コネクタスタブを任意にバインドできます。これにより、適切な SSL 証明書をもつクライアントは、RMI レジストリに登録されたコネクタスタブを取得できます。RMI レジストリを SSL で保護するには、次のシステムプロパティーを設定する必要があります。
com.sun.management.jmxremote.registry.ssl=true |
このプロパティーが true に設定されている場合、 Java VM の起動時に、アウトオブボックスの管理エージェントによって、SSL で保護された RMI レジストリの生成および設定が行われます。このプロパティーのデフォルト値は false です。このプロパティーが true に設定されている場合、全面的なセキュリティーを施すため、次の項で説明されているように SSL クライアント認証を有効にする必要があります。
SSL クライアント認証の有効化
SSL クライアント認証を有効にするには、Java VM の起動時に次のシステムプロパティーを正しく設定します。
com.sun.management.jmxremote.ssl.need.client.auth=true |
クライアント SSL 認証を使用するには、SSL を有効 (デフォルト) にしておく必要があります。この構成では、クライアントシステムが有効なデジタル証明書を持つ必要があります。「SSL の使用」の説明に従って、クライアントシステムに証明書をインストールし、SSL を設定する必要があります。前の項で述べたように、RMI レジストリの SSL 保護を有効にした場合は、クライアント SSL 認証を true に設定する必要があります。
SSL の無効化
リモート監視で SSL を無効にするには、Java VM の起動時に次のシステムプロパティーを設定する必要があります。
com.sun.management.jmxremote.ssl=false |
パスワード認証は、「パスワード認証の無効化」の手順に従って無効にしないかぎり、必要になります。
セキュリティーの無効化
パスワード認証と SSL の両方を無効 (つまりすべてのセキュリティーを無効) にするには、Java VM の起動時に次のシステムプロパティーを設定する必要があります。
com.sun.management.jmxremote.authenticate=false com.sun.management.jmxremote.ssl=false |
警告 - この構成は安全ではありません。ポート番号およびホスト名を知っている (または推測する) リモートユーザーなら誰でも、Java アプリケーションおよびプラットフォームの監視と制御ができます。さらに、危害の可能性は MBean で定義する操作に限定されません。最低限のセキュリティーマネージャーもない場合、リモートクライアントは javax.management.loading.MLet MBean を作成し、それを使用して任意の URL から新しい MBean を作成できます。つまり、悪意のあるリモートクライアントから、Java アプリケーションに任意のコードを実行させることができるということです。
このような理由から、セキュリティーの無効化は、開発時には許容される場合があっても、実稼動システムのセキュリティーでは行わないことを強くお勧めします。
JConsole によるリモート監視
セキュリティーが有効でも無効でも、JConsole を使用してアプリケーションをリモート監視できます。
JConsole によるリモート監視 (SSL が無効な場合)
SSL が無効な状態でリモートアプリケーションを監視するには、次のコマンドで JConsole を起動します。
% jconsole hostName:portNum |
ホスト名とポート番号を省略して、JConsole が提供するダイアログボックスに入力することもできます。
JConsole によるリモート監視 (SSL が有効な場合)
SSL が有効な状態でリモートアプリケーションを監視するには、JConsole が稼動しているシステムでトラストストアを設定し、SSL を正しく設定する必要があります。たとえば、「JSSE ガイド」の手順に従ってキーストアを作成し、次のコマンドでアプリケーション (この例では Server) を起動します。
% java -Djavax.net.ssl.keyStore=keystore \ -Djavax.net.ssl.keyStorePassword=password Server |
キーストアを作成して、前記の Server が起動したら、次のように JConsole を起動する必要があります。
% jconsole -J-Djavax.net.ssl.trustStore=truststore \ -J-Djavax.net.ssl.trustStorePassword=trustword |
この構成はサーバーだけを認証します。クライアント SSL 認証が設定されている場合、同様のキーストアを JConsole のキーに渡し、該当するトラストストアをアプリケーションに渡す必要があります。
詳細は、「JSSE ガイド」の「デフォルトの鍵とトラストストア、ストア型、およびストアパスワードのカスタマイズ」を参照してください。
JConsole の使用に関する詳細は、「第 3章 JConsole の使用」を参照してください。
パスワードとアクセスファイルの使用
パスワードおよびアクセスファイルは、リモート監視および管理のセキュリティーを制御します。これらのファイルは、デフォルトでは JRE_HOME/lib/management にあり、標準の Java プロパティーファイルフォーマットです。フォーマットに関する詳細は、java.util.Properties パッケージの「API リファレンス」を参照してください。
パスワードファイル
パスワードファイルは、各種ロールとそのパスワードを定義します。アクセス制御ファイル (デフォルトでは、jmxremote.access) は、ロールごとに許可するアクセス権を定義します。ロールを機能させるには、パスワードとアクセスファイルの両方にエントリを持つ必要があります。
JRE 実装には、jmxremote.password.template というパスワードファイルテンプレートがあります。このファイルを JRE_HOME/lib/management/jmxremote.password またはホームディレクトリにコピーして、アクセスファイルで定義したロールのパスワードを追加します。
パスワードファイルにはパスワードがクリアテキストで含まれるため、必ず所有者だけがこのファイルへの読み取りおよび書き込みアクセス権を持つようにしてください。セキュリティー上の理由から、システムは所有者だけがファイルを読み取り可能であるか確認し、そうでない場合はエラーとして終了します。このため、マルチユーザー環境では、パスワードファイルをホームディレクトリなどの非公開の場所に保存する必要があります。
プロパティー名はロールで、関連付けられた値はロールのパスワードです。たとえば、パスワードファイルのエントリの例は次のようになります。
例 2-1 パスワードファイルの例
# The "monitorRole" role has password "QED". # The "controlRole" role has password "R&D". monitorRole QED controlRole R&D |
Solaris および Linux システムでパスワードファイルのファイルアクセス権を設定するには、次のコマンドを実行します。
chmod 600 jmxremote.password |
Windows プラットフォームでファイルアクセス権を設定する手順については、付録 A「Microsoft Windows 用のセキュリティー情報の詳細」を参照してください。
アクセスファイル
デフォルトでは、アクセスファイルは jmxremote.access という名前です。プロパティー名はパスワードファイルと同じ領域の ID です。関連する値は readonly または readwrite のいずれかにする必要があります。
アクセスファイルはロールとそのアクセスレベルを定義します。デフォルトでは、アクセスファイルは次の 2 つの主要なロールを定義します。
monitorRole: 監視のための読み取り専用アクセスを許可します。
controlRole: 監視および管理のために読み取りおよび書き込みアクセスを許可します。
アクセス制御エントリは、ロール名と関連するアクセスレベルで構成されています。ロール名には、スペースやタブを含めることはできず、パスワードファイル内のエントリに対応している必要があります。アクセスレベルは次のいずれかです。
readonly: MBean の属性の読み取りアクセスを許可します。これは、監視の場合、このロールのリモートクライアントから測定値を読み取ることはできるが、実行中のプログラムの環境を変更するアクションは実行できないという意味です。リモートクライアントは MBean の通知を待機することもできます。
readwrite: MBean の属性の読み取りおよび書き込みアクセス、MBean の属性への操作の呼び出し、MBean の属性の作成または削除を許可します。アプリケーションの操作を妨げる可能性があるため、このアクセス権は信頼できるクライアントのみに許可する必要があります。
ロールは、アクセスファイル内で 1 つのエントリだけを持つ必要があります。ロールにエントリがない場合、アクセス権はありません。ロールに複数のエントリがある場合、最後のエントリが優先されます。アクセスファイルの事前定義された一般的なロールには、次のようなものがあります。
例 2-2 アクセスファイルの例
# The "monitorRole" role has readonly access. # The "controlRole" role has readwrite access. monitorRole readonly controlRole readwrite |
アウトオブボックスの監視および管理のプロパティー
アウトオブボックスの管理および監視のプロパティーは、構成ファイルまたはコマンド行で設定できます。コマンド行で指定したプロパティーは、構成ファイル内のプロパティーをオーバーライドします。構成ファイルのデフォルトの場所は、JRE_HOME/lib/management/management.properties です。com.sun.management.jmxremote または com.sun.management.jmxremote.port のいずれかのコマンド行プロパティーが設定されている場合、Java VM はこのファイルを読み取ります。SNMP (Simple Network Management Protocol) による管理では、同じ構成ファイルを使用します。SNMP の監視に関する詳細は、第 5 章「SNMP 監視と管理」を参照してください。
次のコマンド行オプションで、構成ファイルの別の位置を指定できます。
com.sun.management.config.file=ConfigFilePath |
上のプロパティーでは、ConfigFilePath が構成ファイルへのパスです。
表 2-1 は、すべてのアウトオブボックスの監視および管理プロパティーを示しています。
表 2-1 アウトオブボックスの監視および管理のプロパティー
プロパティー | 説明 | 値 |
---|---|---|
com.sun.management.jmxremote | JConsole で使用される非公開インタフェース上に公開された JMX コネクタと、Attach API を使用する他のローカルの JMX クライアントから、JMX リモートエージェントおよびローカルの監視を有効にします。JConsole でこのコネクタを使用できるのは、エージェントを起動したときと同じユーザー ID で JConsole を起動した場合です。このコネクタ経由の要求については、パスワードやアクセスファイルはチェックされません。 | true / false。デフォルトは true。 |
com.sun.management.jmxremote. port | JMX リモートエージェントを有効にして、リモート JMX コネクタを作成し、指定したポートで待機します。デフォルトでは、SSL、パスワード、およびアクセスファイルプロパティーがこのコネクタに使用されます。また、com.sun.management.jmxremote プロパティーで説明したローカルの監視も有効にします。 | ポート番号。デフォルトは存在しない |
com.sun.management.jmxremote. registry.ssl | SSL で保護された RMI レジストリに RMI コネクタスタブをバインドします。 | true / false。デフォルトでは false。 |
com.sun.management.jmxremote. ssl | SSL 経由で安全に監視できるようにします。false の場合、SSL は使用されません。 | true / false。デフォルトは true。 |
com.sun.management.jmxremote. ssl.enabled.protocols | 有効にする SSL/TLS プロトコルバージョンのコンマ区切りのリスト。com.sun.management.jmxremote.ssl と組み合わせて使用します。 | デフォルトの SSL/TLS プロトコルバージョン。 |
com.sun.management.jmxremote. ssl.enabled.cipher.suites | 有効にする SSL/TLS 暗号化方式群のコンマ区切りのリスト。com.sun.management.jmxremote.ssl と組み合わせて使用します。 | デフォルトの SSL/TLS 符号化方式。 |
com.sun.management.jmxremote. ssl.need.client.auth | このプロパティーが true でプロパティー com.sun.management.jmxremote.ssl も true の場合、クライアント認証が実行されます。 | true / false。デフォルトは true。 |
com.sun.management.jmxremote. authenticate | このプロパティーが false の場合、JMX ではパスワードもアクセスファイルも使用しません。すべてのユーザーがすべてのアクセスを許可されます。 | true / false。デフォルトは true。 |
com.sun.management.jmxremote. password.file | パスワードファイルの場所を指定します。com.sun.management.jmxremote.authenticate が false の場合、このプロパティーとパスワードおよびアクセスファイルは無視されます。それ以外の場合は、パスワードファイルが存在し、有効な形式である必要があります。パスワードファイルが空であるか存在しない場合、アクセスは許可されません。 | JRE_HOME/lib/management/ jmxremote.password |
com.sun.management.jmxremote. access.file | アクセスファイルの場所を指定します。com.sun.management.jmxremote.authenticate が false の場合、このプロパティーとパスワードおよびアクセスファイルは無視されます。それ以外の場合は、アクセスファイルが存在し、有効な形式である必要があります。アクセスファイルが空であるか存在しない場合、アクセスは許可されません。 | JRE_HOME/lib/management/ jmxremote.access |
com.sun.management.jmxremote. login.config | JMX エージェントがユーザーを認証する場合に使用する JAAS (Java Authentication and Authorization Service) ログイン構成エントリの名前を指定します。このプロパティーを使用してデフォルトのログイン設定をオーバーライドする場合は、指定された構成エントリが JAAS でロードされたファイルに存在する必要があります。また、構成で指定されたログインモジュールは、名前とパスワードのコールバックを使用してユーザーの資格を取得する必要があります。詳細は、javax.security.auth.callback.NameCallback および javax.security.auth.callback.PasswordCallback のAPI ドキュメントを参照してください。 | デフォルトのログイン構成は、ファイルベースのパスワード認証です。 |
構成エラー
MBean サーバー、RMI レジストリ、またはコネクタの起動中にエラーが発生した場合、Java VM は例外をスローして終了します。構成エラーには、次のようなものがあります。
ポート番号に対するバインドの失敗。
無効なパスワードファイル。
無効なアクセスファイル。
パスワードファイルが所有者以外のユーザーから読み取り可能になっている。
アプリケーションでセキュリティーマネージャーを実行する場合、セキュリティーアクセス権ファイルに追加のアクセス権を登録する必要があります。
プログラムによる JMX エージェントへの接続
JMX エージェントを有効にしたら、クライアントから次の URL を使用して監視サービスにアクセスできます。
service:jmx:rmi:///jndi/rmi://hostName:portNum/jmxrmi |
クライアントがエージェントのコネクタを作成するには、例 2-3 のように、URL を使用して javax.management.remote.JMXServiceURL オブジェクトをインスタンス化した後、JMXConnectorFactory.connect メソッドを使用して接続を作成します。
例 2-3 JMXConnectorFactory.connect を使用した接続の作成
JMXServiceURL u = new JMXServiceURL( "service:jmx:rmi:///jndi/rmi://" + hostName + ":" + portNum + "/jmxrmi"); JMXConnector c = JMXConnectorFactory.connect(u); |
プログラムによる監視および管理の設定
前述のように、Java SE プラットフォームのバージョン 6 では、 Attach API を使用する JMX クライアントを作成できます。これによって Java SE 6 プラットフォームで起動する任意のアプリケーションから、起動時に監視用の設定をしなくても、アウトオブボックスの監視および管理ができるようになります。 Attach API は、ツールによってターゲットアプリケーションのエージェントに接続し、それらのエージェントを起動します。エージェントが起動すれば、JMX クライアント (や他のツール) は、そのエージェントに代わって Java VM が保持するプロパティーリストから、そのエージェントの JMX コネクタアドレスを取得できます。このリストに含まれるプロパティーは、Attach API. を使用するツールからアクセスできます。したがって、アプリケーションから起動したエージェントが構成情報を示すプロパティーを生成した場合、その構成情報はアプリケーションに接続するツールから利用できます。
JMX エージェントは、ローカルの JMX コネクタサーバーのアドレスからプロパティーを生成します。これによって、JMX ツールは、起動中のエージェントのコネクタアドレスを取得し、これに接続することができます。
例 2-4 に示すコードを JMX ツールで使用すれば、ターゲット VM に接続し、JMX エージェントのコネクタアドレスを取得し、これに接続することができます。
例 2-4 JMX ツールのコネクタへの接続とエージェントのアドレスの取得
static final String CONNECTOR_ADDRESS = "com.sun.management.jmxremote.localConnectorAddress"; // attach to the target application VirtualMachine vm = VirtualMachine.attach(id); // get the connector address String connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS); // no connector address, so we start the JMX agent if (connectorAddress == null) { String agent = vm.getSystemProperties().getProperty("java.home") + File.separator + "lib" + File.separator + "management-agent.jar"; vm.loadAgent(agent); // agent is started, get the connector address connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS); } // establish connection to connector server JMXServiceURL url = new JMXServiceURL(connectorAddress); JMXConnector = JMXConnectorFactory.connect(url); |
例 2-4 は、com.sun.tools.attach.VirtualMachine クラスの attach() メソッドを使用して、指定された Java VM に接続することにより、ターゲット Java VM が稼動中のエージェントに代わって保持するプロパティーを、指定された Java VM で読み取ることができるようになっています。エージェントがすでに起動している場合は、VirtualMachine クラスの getAgentProperties() メソッドを呼び出し、そのエージェントのアドレスを取得します。ローカルのコネクタアドレス com.sun.management.jmxremote.localConnectorAddress の場合、getAgentProperties() メソッドは文字列プロパティーを返します。これを使用すれば、ローカルの JMX エージェントに接続できます。
起動中のエージェントがない場合、JRE_HOME/lib/management-agent.jar からいずれかのエージェントが VirtualMachine によってロードされます。そのコネクタアドレスは getAgentProperties() によって得られます。
次に、エージェントへの接続を確立するには、このコネクタアドレスから構築された JMX サービス URL の JMXConnectorFactory.connect を呼び出します。
JMX リモート API を使用したアウトオブボックスの管理の模倣
前述のように、アウトオブボックスの管理エージェントへのリモートアクセスは、認証と承認、および SSL 暗号化によって保護されています。あらゆる設定は、システムプロパティーの設定または management.properties ファイルの定義によって行われます。ほとんどの場合、アウトオブボックスの管理エージェントを使用し、これを management.properties ファイルで設定すれば、リモート Java VM の管理の安全性は十分です。ただし、さらに高いレベルのセキュリティーが必要な場合もあれば、システム構成によっては management.properties ファイルが使用できない場合もあります。このような場合には、ファイアウォールを通過できるように RMI サーバーのリモートオブジェクトを特定のポートにエクスポートすること、あるいはマルチホームシステムで特定のネットワークインタフェースを使用して RMI サーバーのリモートオブジェクトをエクスポートすることもあります。このような場合、JMX リモート API を使用して直接プログラムから管理エージェントの作成、構成、配備を行うことで、アウトオブボックスの管理エージェントの動作は模倣されます。
アウトオブボックスの管理の模倣の例
このセクションでは、アウトオブボックスの管理エージェントをまったく同じものとして模倣する JMX エージェントの実装方法を例示します。アウトオブボックスの管理エージェントとまったく同様に、例 2-5 で作成されたエージェントはポート 3000 で動作し、password.properties というパスワードファイルと access.properties というアクセスファイルをもち、SSL/TLS ベースの RMI ソケットファクトリのデフォルトの構成を実装し、サーバー認証だけを必要とします。この例は、「SSLの使用」で説明しているように、keystore がすでに作成されていることを前提としています。SSL 構成の設定方法については、「JSSE リファレンスガイド」を参照してください。
前記のように構成されたアウトオブボックスの JMX エージェントを使用して com.example.MyApp というアプリケーションの監視と管理を有効にするには、次のコマンドで com.example.MyApp を起動します。
% java -Dcom.sun.management.jmxremote.port=3000 \ -Dcom.sun.management.jmxremote.password.file=password.properties \ -Dcom.sun.management.jmxremote.access.file=access.properties \ -Djavax.net.ssl.keyStore=keystore \ -Djavax.net.ssl.keyStorePassword=password \ com.example.MyApp |
注 - com.sun.management.jmxremote.* プロパティーは、コマンド行で渡す代わりに management.properties ファイルで指定することもできます。その場合は、システムプロパティー -Dcom.sun.management.config.file=management.properties で、management.properties ファイルの場所を指定する必要があります。
例 2-5 は、com.example.MyApp で前記のコマンドを使用した場合とまったく同じ監視および管理ができる JMX エージェントをプログラムによって作成する場合に、記述が必要なコードを示しています。
例 2-5 プログラムによるアウトオブボックスの JMX エージェントの模倣
package com.example; import java.lang.management.*; import java.rmi.registry.*; import java.util.*; import javax.management.*; import javax.management.remote.*; import javax.management.remote.rmi.*; import javax.rmi.ssl.*; public class MyApp { public static void main(String[] args) throws Exception { // Ensure cryptographically strong random number generator used // to choose the object number - see java.rmi.server.ObjID // System.setProperty("java.rmi.server.randomIDs", "true"); // Start an RMI registry on port 3000. // System.out.println("Create RMI registry on port 3000"); LocateRegistry.createRegistry(3000); // Retrieve the PlatformMBeanServer. // System.out.println("Get the platform's MBean server"); MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); // Environment map. // System.out.println("Initialize the environment map"); HashMap<String,Object> env = new HashMap<String,Object>(); // Provide SSL-based RMI socket factories. // // The protocol and cipher suites to be enabled will be the ones // defined by the default JSSE implementation and only server // authentication will be required. // SslRMIClientSocketFactory csf = new SslRMIClientSocketFactory(); SslRMIServerSocketFactory ssf = new SslRMIServerSocketFactory(); env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, csf); env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, ssf); // Provide the password file used by the connector server to // perform user authentication. The password file is a properties // based text file specifying username/password pairs. // env.put("jmx.remote.x.password.file", "password.properties"); // Provide the access level file used by the connector server to // perform user authorization. The access level file is a properties // based text file specifying username/access level pairs where // access level is either "readonly" or "readwrite" access to the // MBeanServer operations. // env.put("jmx.remote.x.access.file", "access.properties"); // Create an RMI connector server. // // As specified in the JMXServiceURL the RMIServer stub will be // registered in the RMI registry running in the local host on // port 3000 with the name "jmxrmi". This is the same name the // out-of-the-box management agent uses to register the RMIServer // stub too. // System.out.println("Create an RMI connector server"); JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:3000/jmxrmi"); JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs); // Start the RMI connector server. // System.out.println("Start the RMI connector server"); cs.start(); } } |
次のコマンドでこのアプリケーションを起動します。
java -Djavax.net.ssl.keyStore=keystore \ -Djavax.net.ssl.keyStorePassword=password \ com.example.MyApp |
com.example.MyApp アプリケーションにより、JMX エージェントが有効になり、Java プラットフォームのアウトオブボックスの管理エージェントを使用した場合とまったく同様に監視と管理ができるようになります。ただし、アウトオブボックスの管理エージェントで使用する RMI レジストリとそれを模倣した管理エージェントで使用する RMI レジストリ とでは、わずかながら重要な違いが 1 つあります。アウトオブボックスの管理エージェントで使用する RMI レジストリは読み取り専用です。つまり、これにバインドできるのは単一のエントリであり、一度バインドされたエントリはもうアンバインドできません。これは例 2-5 で作成された RMI レジストリには当てはまりません。
そのほか、どちらの RMI レジストリも、SSL/TLS を使用しないため、安全ではありません。RMI レジストリは、クライアント認証を必要とする SSL/TLS ベースの RMI ソケットファクトリを使用して作成するべきです。そうすれば、クライアントの資格が悪意のある RMI サーバーに送信されることはなく、RMI レジストリが信頼できないクライアントに RMI サーバースタブへのアクセスを許すこともありません。
SSL/TLS RMI ソケットファクトリを実装する RMI レジストリは、management.properties ファイルに次のプロパティーを追加することで作成できます。
com.sun.management.jmxremote.registry.ssl=true com.sun.management.jmxremote.ssl.need.client.auth=true |
例 2-5 では、アウトオブボックスの JMX エージェントの主な動作を模倣していますが、management.properties ファイルにある既存のプロパティーのすべてを複製しているわけではありません。ただし、com.example.MyApp を適切に変更すれば、他のプロパティーを追加できます。
ファイアウォールを介したアプリケーションの監視
前述のように、例 2-5 のコードを使用すればファイアウォールを介してアプリケーションの監視ができますが、アウトオブボックスの監視ソリューションではこれができない場合もあります。com.sun.management.jmxremote.port 管理プロパティーは、RMI レジストリに接続可能なポートを正しく指定しても、RMI スタックは RMIServer および RMIConnection リモートオブジェクトがエクスポートされるポートを選択します。リモートオブジェクト (RMIServer と RMIConnection) を指定されたポートにエクスポートするには、例 2-5 のように、プログラムによって RMI コネクタサーバーを作成する必要があります。ただし、JMXServiceURL は必ず次のように指定します。
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://localhost:" + port1 + "/jndi/rmi://localhost:" + port2 + "/jmxrmi"); |
この URL の中の port1 は RMIServer および RMIConnection リモートオブジェクトがエクスポートされるポート番号、port2 は RMI レジストリのポート番号です。
エージェントクラスを使用するアプリケーションの計測
Java SE プラットフォームは、Java プログラミング言語エージェントにより Java VM で実行中のプログラムを計測するサービスを提供します。インストゥルメンテーションエージェントを作成すれば、アプリケーションを監視する場合、そのアプリケーションに新しいコードを追加する必要がなくなります。監視と管理は、アプリケーションの static main メソッドに実装するのではなく別のエージェントクラスに実装し、-javaagent オプションを指定することでアプリケーションを起動します。エージェントクラスを作成してアプリケーションを計測する方法の詳細は、java.lang.instrument パッケージの API リファレンスドキュメントを参照してください。
次の手順は、com.example.MyApp のコードを改変して、エージェントに監視および管理用の他のアプリケーションを計測させる方法を示しています。
エージェントクラスの作成によるアプリケーションの計測
com.example.MyAgent クラスを作成します。
com.example.MyAgent というクラスを作成し、main メソッドではなく premain メソッドを宣言します。
package com.example; [...] public class MyAgent { public static void premain(String args) throws Exception { [...]
com.example.MyAgent クラスの残りのコードは、例 2-5 に示した com.example.MyApp クラスとまったく同じでも構いません。
com.example.MyAgent クラスをコンパイルします。
Premain-Class エントリを使用して、マニフェストファイル MANIFEST.MF を作成します。
エージェントは Java アーカイブ (JAR) ファイルとして配備されます。JAR ファイルに含まれるマニフェストの属性は、エージェントを起動するためにロードされるエージェントクラスを指定します。MANIFEST.MF というファイルを作成し、次の行を挿入します。
Premain-Class: com.example.MyAgent
JAR ファイル MyAgent.jar を作成します。
JAR ファイルには必ず次のファイルを入れます。
META-INF/MANIFEST.MF
com/example/MyAgent.class
アプリケーションを起動し、監視および管理サービスを提供するエージェントを指定します。
com.example.MyAgent を使用すれば、監視および管理用のアプリケーションを計測できます。次の例では、アプリケーションとして Notepad を使用します。
% java -javaagent:MyAgent.jar -Djavax.net.ssl.keyStore=keystore \ -Djavax.net.ssl.keyStorePassword=password -jar Notepad.jar
Notepad を起動するとき、-javaagent オプションを使用して、com.example.MyAgent エージェントを指定します。また、com.example.MyAgent アプリケーションが例 2-5 の com.example.MyApp アプリケーションと同じコードを複製する場合、RMI コネクタサーバーは SSL で保護されているため、keystore と password が必要になります。