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でサポートされているコマンド行オプションの構文と完全なセットについては、Java Platform, Standard Editionツール・リファレンスのJavaアプリケーション・ランチャのセクションを参照してください。
JMX APIを使用してJavaプラットフォームをモニターするには、次の手順を実行する必要があります。
Java VMの起動時にJMXエージェント(プラットフォームMBeanサーバーの別名)を有効にします。JMXエージェントの有効範囲は次のとおりです。
ローカル・モニタリング、ローカル・システムで実行されるクライアント管理アプリケーション。
リモート・モニタリング、リモート・システムで実行されるクライアント管理アプリケーション。
JMX仕様に準拠したツール(JConsoleなど)でJava VMをモニターします。JConsoleの使用を参照してください。
以前は、Java VMまたはJavaアプリケーションの起動時に、JMXクライアントがローカルJava VMにアクセスできるように次のプロパティを設定していました。
com.sun.management.jmxremote
このプロパティを設定すると、Java VMプラットフォームのMBeanが登録され、プライベート・インタフェースを介してRemote Method Invocation (RMI)コネクタが公開されました。この設定により、JMXクライアント・アプリケーションでローカルJavaプラットフォーム(つまり、JMXクライアントと同じマシンで実行されているJava VM)をモニターすることが可能になります。
現在のJava SEプラットフォームでは、このシステム・プロパティの設定は必要ありません。どのアプリケーションでも、現在のJava SEプラットフォームで起動したものであれば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プラットフォームでは、次のコマンドを実行して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
を起動すると、ローカルのJavaアプリケーションがすべて自動検出され、モニター対象とするアプリケーションを選択できるダイアログ・ボックスが表示されます。JConsoleとアプリケーションはどちらも、同じユーザーが実行する必要があります。モニタリングおよび管理システムには、オペレーティング・システムのファイル・アクセス権を使用するためです。
注意:
コマンド行からJConsoleを実行するには、JDK_HOME/bin
をパスに追加する必要があります。または、コマンドを入力するときにフルパスを入力することもできます。JConsoleの使用を参照してください。デフォルトでは、ローカルで作成されたリモート・オブジェクトについて、クライアントに送信されるリモート・スタブにローカル・ホストのIPアドレスがdotted-quad
形式で含まれます。リモート・スタブを特定のインタフェース・アドレスと関連付けるには、java.rmi.server.hostname
システム・プロパティをそのインタフェースのIPアドレスに設定する必要があります。
リモート・システムからモニタリングと管理を行うには、Java VM起動時に次のシステム・プロパティを設定する必要があります。
com.sun.management.jmxremote.port=portNum
portNum
はJMX RMI接続に使用するポート番号です。必ず未使用のポート番号を指定してください。ローカル・アクセス用にRMIコネクタが公開されるのに加えて、このプロパティを設定することにより、jmxrmi
という名前を使用して、指定したポートの非公開の読取り専用レジストリに追加のRMIコネクタが公開されます。システム・プロパティを使用してRMIコネクタがバインドされるポート番号: com.sun.management.jmxremote.rmi.port
必ず未使用のポート番号を使用してください。
注意:
セキュリティ用に設定するプロパティに加えて、前述のシステム・プロパティを設定する必要があります。リモート・モニタリングと管理には、権限のない人がアプリケーションの制御やモニターができないように、セキュリティが必要です。デフォルトで、SSL (secure sockets layer)経由のパスワード認証とTLS (Transport Layer Security)が有効になっています。パスワード認証とSSLは別々に無効にすることができます。
Javaプラットフォームでは、認証にプラガブルなログイン・モジュールがサポートされます。組織の認証インフラストラクチャに応じて、任意のログイン・モジュールをプラグインできます。LDAP認証の使用では、Lightweight Directory Access Protocol (LDAP)ベースの認証にcom.sun.security.auth.module.LdapLoginModuleモジュールをプラグインする方法について説明します。
JMXエージェントをリモートで使用可能にすると、「JConsoleによるリモート・モニタリング」に説明するように、JConsoleでアプリケーションをモニタリングできます。プログラムから管理エージェントに接続する方法については、「プログラムによるJMXエージェントへの接続」を参照してください。
このセクションでは、要件に応じて実装可能な異なるパスワード認証方式について説明します。
JMXエージェントでのJMXAuthenticatorの実装は、Java認証・承認サービス(JAAS)テクノロジに基づいています。認証は、ユーザー資格証明をJAASのjavax.security.auth.spi.LoginModuleオブジェクトに渡すことで実行されます。 com.sun.security.auth.module.LdapLoginModuleクラスは、LDAPを使用した認証を可能にします。デフォルトのLoginModule
クラスをLdapLoginModule
クラスで置き換えることができます。
必要なビジネス組織で機能するJAAS構成ファイルを作成します。構成ファイル(ldap.config
)の例を次に示します。
ExampleCompanyConfig { com.sun.security.auth.module.LdapLoginModule REQUIRED userProvider="ldap://example-ds/ou=people,dc=examplecompany,dc=com" userFilter="(&(uid={USERNAME})(objectClass=inetOrgPerson))" authzIdentity=monitorRole; };
構成ファイルに示されているオプションの概要を次に示します。
com.sun.security.auth.module.LdapLoginModule REQUIRED
オプションは、認証全体を正常に行うためにLdapLoginModule
を使用した認証が必要なことを意味します。 userProvider
オプションは、LDAPサーバー、およびユーザー・エントリがあるディレクトリ・ツリー内の位置を特定します。 userFilter
オプションは、LDAPディレクトリ内のユーザー・エントリの検索に使用する検索フィルタを指定します。フィルタを使用してディレクトリを検索する前に、トークン{USERNAME}
はユーザー名と置き換えられます。authzIdentity
オプションは、認証されたユーザーのアクセス・ロールを指定します。例では、認証されたユーザーはmonitorRole
を持ちます。アクセス・ファイルを参照してください。コード例に示されている構成オプションの詳細は、com.sun.security.auth.module.LdapLoginModuleクラスを参照してください。
コマンド行で次のプロパティを設定して、アプリケーションを起動します。
com.sun.management.jmxremote.login.config
: このプロパティは、指定したJAAS構成エントリを使用するようJMXエージェントを構成します。java.security.auth.login.config
: このプロパティは、JAAS構成ファイルへのパスを指定します。コマンド行の例を次に示します。
java -Dcom.sun.management.jmxremote.port=5000 -Dcom.sun.management.jmxremote.login.config=ExampleCompanyConfig -Djava.security.auth.login.config=ldap.config -jar MyApplication.jar
JMXエージェントによってサポートされるファイルベースのパスワード認証メカニズムは、パスワードをクリアテキストで格納し、開発での使用のみを目的としています。本番での使用の場合、認証にSSLクライアント証明書を使用するか、セキュアなログイン構成をプラグインすることをお薦めします。
注意:
警告: クライアントがセキュアではないRMIレジストリ(デフォルト)からリモート・コネクタを取得すると、リモート・コネクタからのパスワード認証でセキュリティの問題が発生する可能性があります。ターゲット・サーバー上で正当なRMIレジストリが起動する前に攻撃者が偽のRMIレジストリを起動すれば、クライアントのパスワードを盗むことができます。このシナリオは、システム・プロパティcom.sun.management.jmxremote.port=portNum
でリモート管理を有効にしてJava VMを起動する場合も当てはまります。SSLが有効になっていても同じです。このような攻撃者は発見されることが多いものの、脆弱性があることは確かです。デフォルトでは、リモート・モニタリングで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
などのロールのパスワードを追加します。com.sun.management.jmxremote.password.file=pwFilePath
前述のプロパティのpwFilePath
は、パスワード・ファイルへのパスです。
リモート・モニタリングのパスワード認証は、デフォルトで有効になっています。パスワード認証を無効にするには、Java VMの起動時に次のシステム・プロパティを設定します。
com.sun.management.jmxremote.authenticate=false
注意:
警告: この構成はセキュアではありません。JMXポート番号およびホスト名を知っている(または推測する)リモート・ユーザーならだれでも、Javaアプリケーションおよびプラットフォームのモニターと制御ができます。開発用には許容される場合があっても、実稼動システムにはお薦めしません。パスワード認証を無効にする場合、「セキュリティの無効化」で説明しているようにSSLを無効にすることもできます。SSLクライアント認証の有効化で説明しているように、パスワードを無効にしてSSLクライアント認証を使用することもできます。
リモート・モニタリングおよび管理を有効にすると、SSLはデフォルトで有効になっています。SSLを使用するには、JMXエージェント(MBeanサーバー)が稼動するシステム上でデジタル証明書を設定して、次にSSLを正しく構成する必要があります。コマンド行ユーティリティkeytool
を使用して、証明書を操作します。
SSLを設定する一般的な手順は次のとおりです。
keytool -genkey
コマンドで鍵ペアを生成します。
keytool -certreq
コマンドで認証局(CA)に署名付き証明書を要求します。
keytool -import
コマンドで、証明書をキーストアにインポートします。keytool
のドキュメントで証明書のインポートを参照してください。
javax.net.ssl.keyStore |
キーストアの場所 |
javax.net.ssl.keyStoreType |
デフォルトのキーストア・タイプ |
javax.net.ssl.keyStorePassword |
デフォルトのキーストア・パスワード |
javax.net.ssl.trustStore |
トラストストアの場所 |
javax.net.ssl.trustStoreType |
デフォルトのトラストストア・タイプ |
javax.net.ssl.trustStorePassword |
デフォルトのトラストストア・パスワード |
システム・プロパティの設定については、システム・プロパティの設定のセクションを参照してください。
参照:
Java Platform, Standard Editionセキュリティ開発者ガイドのデフォルトのキーストアとトラストストア、ストア・タイプ、およびストア・パスワードのカスタマイズ
リモート・アプリケーションのモニタリングで接続を設定するとき、SSLで保護されているRMIレジストリにRMIコネクタ・スタブをオプションでバインドできます。これにより、適切なSSL証明書を持つクライアントは、RMIレジストリに登録されたコネクタ・スタブを取得できます。RMIレジストリをSSLで保護するには、次のシステム・プロパティを設定する必要があります。
com.sun.management.jmxremote.registry.ssl=true
このプロパティがtrue
に設定されている場合、Java VMの起動時に、すぐに使用できる管理エージェントによって、SSLで保護されたRMIレジストリの生成および構成が行われます。このプロパティのデフォルト値はfalse
です。ただし、このプロパティはtrue
に設定することをお薦めします。このプロパティがtrue
に設定されている場合、全面的なセキュリティを施すため、SSLクライアント認証を有効にする必要もあります。
SSLクライアント認証を有効にするには、Java VMの起動時に次のシステム・プロパティを設定します。
com.sun.management.jmxremote.ssl.need.client.auth=true
クライアントSSL認証を使用するには、SSLを有効(デフォルトはfalse
に設定されます)にしておく必要があります。このプロパティはtrue
に設定することをお薦めします。この構成では、クライアント・システムが有効なデジタル証明書を持つ必要があります。「SSLの使用」の説明に従って、クライアント・システムに証明書をインストールし、SSLを構成する必要があります。前のセクションで述べたように、RMIレジストリのSSL保護を有効にした場合は、クライアントSSL認証をtrue
に設定する必要があります。
リモート・モニタリングで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アプリケーションに任意のコードを実行させることができるということです。このような理由から、セキュリティの無効化は、開発時には許容される場合があっても、実稼動システムのセキュリティでは行わないことを強くお薦めします。
SSLが有効な状態でリモート・アプリケーションをモニターするには、JConsoleが稼動しているシステムでtruststore
ファイルを設定し、SSLを正しく構成する必要があります。たとえば、keystore
ファイルを作成し、次のコマンドでアプリケーション(この例ではServer
)を起動します。
% java -Djavax.net.ssl.keyStore=keystore \ -Djavax.net.ssl.keyStorePassword=password Server
Java Platform, Standard Editionセキュリティ開発者ガイドのデフォルトのキーストアとトラストストア、ストア・タイプ、およびストア・パスワードのカスタマイズを参照してください。
keystore
ファイルを作成してServer
アプリケーションを起動する場合、次のようにJConsoleを起動します。
% jconsole -J-Djavax.net.ssl.trustStore=truststore \ -J-Djavax.net.ssl.trustStorePassword=trustword
JConsoleの使用を参照してください。
この構成により認証されるのは、サーバーのみです。クライアントSSL認証が設定されている場合、同様のkeystore
ファイルをJConsoleのキーに渡し、該当するtruststore
ファイルをアプリケーションに渡す必要があります。
パスワードおよびアクセス・ファイルは、リモート・モニタリングおよび管理のセキュリティを制御します。これらのファイルは、デフォルトではJRE_HOME/lib/management
にあり、標準のJavaプロパティ・ファイル・フォーマットです。フォーマットに関する詳細は、java.util.Propertiesパッケージの「APIリファレンス」を参照してください。
パスワード・ファイルは、各種ロールとそのパスワードを定義します。アクセス制御ファイル(デフォルトでは、jmxremote.access
)は、ロールごとに許可するアクセス権を定義します。ロールを機能させるには、パスワードとアクセス・ファイルの両方にエントリを持つ必要があります。
JRE実装には、jmxremote.password.template
というパスワード・ファイル・テンプレートがあります。このファイルをホーム・ディレクトリのjre_home/lib/management/jmxremote.password
にコピーして、アクセス・ファイルで定義したロールのパスワードを追加します。
パスワード・ファイルにはパスワードがクリアテキストで含まれるため、必ず所有者だけがこのファイルへの読取りおよび書込みアクセス権を持つようにしてください。セキュリティ上の理由から、システムは所有者だけがファイルを読取り可能であるか確認し、そうでない場合はエラーとして終了します。このため、マルチユーザー環境では、パスワード・ファイルをホーム・ディレクトリなどの非公開の場所に保存する必要があります。
プロパティ名はロールで、関連付けられた値はロールのパスワードです。例2–1に、パスワード・ファイルのエントリの例を示します。
例 2-1パスワード・ファイルの例
# specify actual password instead of the text password monitorRole password controlRole password
Solaris、LinuxまたはmacOSオペレーティング・システムで、パスワード・ファイルのファイル・アクセス権を設定するには、次のコマンドを実行します。
chmod 600 jmxremote.password
デフォルトでは、アクセス・ファイルはjmxremote.access
という名前です。プロパティ名はパスワード・ファイルと同じ領域のIDです。関連する値はreadonly
またはreadwrite
のいずれかにする必要があります。
アクセス・ファイルはロールとそのアクセス・レベルを定義します。デフォルトでは、アクセス・ファイルは次の主要なロールを定義します。
monitorRole
: モニタリングのための読取り専用アクセスを許可します。
controlRole
: モニタリングおよび管理のために読取り/書込みアクセスを許可します。
readonly
: MBeanの属性の読取りアクセスを許可します。これは、モニタリングの場合、このロールのリモート・クライアントから測定値を読み取ることはできるが、実行中のプログラムの環境を変更するアクションは実行できないという意味です。リモート・クライアントはMBeanの通知を待機することもできます。
readwrite
: MBeanの属性の読取りおよび書込み、MBeanの属性への操作の呼び出し、MBeanの属性の作成または削除のためのアクセスを許可します。アプリケーションの操作を妨げる可能性があるため、このアクセス権は信頼できるクライアントのみに許可する必要があります。
ロールは、アクセス・ファイル内で1つのエントリだけを持つ必要があります。ロールにエントリがない場合、アクセス権はありません。ロールに複数のエントリがある場合、最後のエントリが優先されます。アクセス・ファイルの事前定義された一般的なロールには、例2-2に示すようなものがあります。
例 2-2アクセス・ファイルの例
# The "monitorRole" role has readonly access. # The "controlRole" role has readwrite access. monitorRole readonly controlRole readwrite
SSLが無効な状態でリモート・アプリケーションをモニターするには、次のコマンドでJConsoleを起動します。
% jconsole hostName:portNum
ホスト名とポート番号を省略して、JConsoleが提供するダイアログ・ボックスに入力することもできます。
すぐに使用できるモニタリングおよび管理のプロパティは、構成ファイルまたはコマンド行で設定できます。コマンド行で指定したプロパティにより、構成ファイル内のプロパティをオーバーライドします。構成ファイルのデフォルトの場所は、jre_home/lib/management/management.properties
です。次のいずれかのコマンド行プロパティが設定されている場合、Java VMはこのファイルを読み取ります。
com.sun.management.jmxremote
com.sun.management.jmxremote.port
SNMP (Simple Network Management Protocol)による管理では、同じ構成ファイルを使用します。SNMPモニタリングと管理を参照してください。
次のコマンド行オプションで、構成ファイルに別の場所を指定できます。
com.sun.management.config.file=ConfigFilePath
ConfigFilePath
は、構成ファイルへのパスです。
表2-1に、すぐに使用できるモニタリングおよび管理のプロパティを示します。
表2-1 すぐに使用できるモニタリングおよび管理のプロパティ
プロパティ | 説明 | 値 |
---|---|---|
|
JMXコネクタを使用して、JMXリモート・エージェントおよびローカル・モニタリングを有効にします。このエージェントは、JConsoleおよび(Attach APIを使用する)その他のローカルJMXクライアントによって使用されるプライベート・インタフェースで公開されます。JConsoleがこのコネクタを使用できるのは、エージェントを起動したユーザーがそのコネクタも起動した場合です。このコネクタからの要求については、パスワードまたはアクセス・ファイルはチェックされません。 |
|
|
JMXリモート・エージェントを有効にして、リモートJMXコネクタを作成し、指定したポートで待機します。デフォルトでは、SSL、パスワード、およびアクセス・ファイル・プロパティがこのコネクタに使用されます。また、 |
ポート番号。デフォルトなし。 |
|
RMIコネクタ・スタブを、SSLで保護されたRMIレジストリにバインドします。 |
|
|
SSLを使用してセキュアなモニタリングを可能にします。値が |
|
|
有効にするSSL/TLSプロトコル・バージョンのカンマ区切りのリストを表示します。 |
デフォルトのSSL/TLSプロトコル・バージョン。 |
|
有効にするSSL/TLS暗号化方式のカンマ区切りのリストを表示します。 |
デフォルトのSSL/TLS暗号化方式。 |
|
このプロパティが このプロパティは |
|
|
このプロパティが |
|
|
パスワード・ファイルの場所を指定します。 |
|
|
アクセス・ファイルの場所を指定します。 |
|
|
JMXエージェントがユーザーを認証する場合に使用するJAAS (Java認証・承認サービス)ログイン構成エントリの名前を指定します。このプロパティを使用してデフォルトのログイン構成をオーバーライドする場合は、指定された構成エントリがJAASでロードされたファイルに存在する必要があります。また、構成で指定されたログイン・モジュールは、名前とパスワードのコールバックを使用してユーザーの資格証明を取得する必要があります。詳細は、 |
デフォルトのログイン構成は、ファイルベースのパスワード認証です。 |
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);
Attach APIを使用するJMXクライアントを作成することで、Java SE 9プラットフォームで起動する任意のアプリケーションに対して、すぐに使用できるモニタリングおよび管理を有効化できます。アプリケーションの起動時にモニター対象として構成する必要はありません。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
を呼び出します。
すぐに使用できる管理エージェントへのリモート・アクセスは、認証・承認に加え、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構成の設定方法の詳細は、Java Platform, Standard Editionセキュリティ開発者ガイドの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 that the // ready-to-use management agent uses to register the RMIServer // stub. // 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 Registryが接続可能なポートが指定されますが、RMIServer
およびRMIConnection
リモート・オブジェクトがエクスポートされるポートは、RMIスタックにより選択されます。リモート・オブジェクト(RMIServer
とRMIConnection
)を指定されたポートにエクスポートするには、例2-5のように、プログラムによってRMIコネクタ・サーバーを作成する必要があります。ただし、JMXServiceURL
は次のように指定する必要があります。
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://localhost:" + port1 + "/jndi/rmi://localhost:" + port2 + "/jmxrmi");
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
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
の情報を指定します。