2 JMXテクノロジを使用するモニタリングと管理

Java仮想マシン(Java VM)は組込みインストゥルメンテーションを備え、これによってJava Management Extensions (JMX)テクノロジを使用したモニターと管理を行うことができます。これらの組込み管理ユーティリティは通常、Java VMのアウトオブボックスの管理ツールと呼ばれます。適切に計測されたアプリケーションであれば、JMX APIを使用してモニターできます。

システム・プロパティの設定

すぐに使用できるJMXエージェントを有効にして、Java VMのモニターと管理ができるように構成するには、Java VMの起動時に特定のシステム・プロパティを設定する必要があります。システム・プロパティは、コマンド行で次のように設定します。

java -Dproperty=value ...

このようにシステム・プロパティはいくつでも設定できます。管理プロパティは、値を指定しないとデフォルト値に設定されます。すぐに使用できる管理プロパティの完全なセットについては、表2-1を参照してください。すぐに使用できるモニタリングと管理のプロパティのセクションで説明しているように、構成ファイルでシステム・プロパティを設定することもできます。

ノート:

コマンド行からJava VMを実行するには、パスにJAVA_HOME/binを追加する必要があります。JAVA_HOMEはJDKがインストールされているディレクトリです。または、コマンドを入力するときにフルパスを入力することもできます。

Java HotSpot VMでサポートされているコマンド行オプションの構文と完全なセットについては、Java Development Kitツール仕様javaに関する項を参照してください。

すぐに使用できる管理の有効化

JMX APIを使用してJavaプラットフォームをモニターするには、次の手順を実行する必要があります。

  1. Java VMの起動時にJMXエージェント(プラットフォームMBeanサーバーの別名)を有効にします。JMXエージェントの有効範囲は次のとおりです。

    • ローカル・モニタリング、ローカル・システムで実行されるクライアント管理アプリケーション。

    • リモート・モニタリング、リモート・システムで実行されるクライアント管理アプリケーション。

  2. 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と入力してツールを起動します。引数なしで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は別々に無効にすることができます。

ノート:

実稼働システムの場合、クライアント・ホストを認証するSSLクライアント証明書とユーザー管理用のパスワード認証の両方を使用します。SSLの使用およびLDAP認証の使用を参照してください。

Javaプラットフォームでは、認証にプラガブルなログイン・モジュールがサポートされます。組織の認証インフラストラクチャに応じて、任意のログイン・モジュールをプラグインできます。LDAP認証の使用では、Lightweight Directory Access Protocol (LDAP)ベースの認証にcom.sun.security.auth.module.LdapLoginModuleモジュールをプラグインする方法について説明します。

JMXエージェントをリモートで使用可能にすると、「JConsoleによるリモート・モニタリング」に説明するように、JConsoleでアプリケーションをモニタリングできます。プログラムから管理エージェントに接続する方法については、「プログラムによるJMXエージェントへの接続」を参照してください。

パスワード認証の使用

このセクションでは、要件に応じて実装可能な異なるパスワード認証方式について説明します。

LDAP認証の使用

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などのパスワード・ファイルで指定したユーザー名を使用します。パスワードとアクセス・ファイルの使用を参照してください。

シングル・ユーザー環境を設定する方法

JAVA_HOME/conf/managementディレクトリのパスワード・ファイルを、次のように設定します。

  1. パスワード・テンプレート・ファイルjmxremote.password.templatejmxremote.passwordにコピーします。
  2. ファイル所有者だけがパスワード・ファイルを読書きできるように、ファイルのアクセス権を設定します。
  3. monitorRolecontrolRoleなどのロールのパスワードを追加します。
マルチユーザー環境を設定する方法

JAVA_HOME/conf/managementディレクトリのパスワード・ファイルを、次のように設定します。

  1. パスワード・テンプレート・ファイルjmxremote.password.templateをホーム・ディレクトリにコピーし、そのファイル名をjmxremote.passwordに変更します。
  2. 自分だけがパスワード・ファイルを読書きできるように、ファイルのアクセス権を設定します。
  3. monitorRolecontrolRoleなどのロールのパスワードを追加します。
  4. Java VMの起動時に、次のシステム・プロパティを設定します。
    com.sun.management.jmxremote.password.file=pwFilePath

    前述のプロパティのpwFilePathは、パスワード・ファイルへのパスです。

パスワード認証の無効化

リモート・モニタリングのパスワード認証は、デフォルトで有効になっています。パスワード認証を無効にするには、Java VMの起動時に次のシステム・プロパティを設定します。

com.sun.management.jmxremote.authenticate=false

ノート:

警告: この構成はセキュアではありません。JMXポート番号およびホスト名を知っている(または推測する)リモート・ユーザーならだれでも、Javaアプリケーションおよびプラットフォームのモニターと制御ができます。開発用には許容される場合があっても、実稼動システムにはお薦めしません。

パスワード認証を無効にする場合、「セキュリティの無効化」で説明しているようにSSLを無効にすることもできます。SSLクライアント認証の有効化で説明しているように、パスワードを無効にしてSSLクライアント認証を使用することもできます。

SSLの使用

リモート・モニタリングおよび管理を有効にすると、SSLはデフォルトで有効になっています。SSLを使用するには、JMXエージェント(MBeanサーバー)が稼動するシステム上でデジタル証明書を設定して、次にSSLを正しく構成する必要があります。コマンド行ユーティリティkeytoolを使用して、証明書を操作します。

SSLを設定する一般的な手順は次のとおりです。

  1. キー・ペアと証明書がサーバーに設定されていない場合は、次のタスクを実行します。
    • keytool -genkeyコマンドでキー・ペアを生成します。

    • keytool -certreqコマンドで認証局(CA)に署名付き証明書を要求します。

    • keytool -importコマンドで、証明書をキーストアにインポートします。keytoolのドキュメントで証明書のインポートを参照してください。

  2. サーバー・システム上でSSLを構成します。このドキュメントでは、SSLの構成とカスタマイズについて詳細には説明しませんが、通常は次のリストに記載されているシステム・プロパティを設定する必要があります。

    システム・プロパティの設定については、システム・プロパティの設定のセクションを参照してください。

    参照:

RMIレジストリ認証の有効化

リモート・アプリケーションのモニタリングで接続を設定するとき、SSLで保護されているRMIレジストリにRMIコネクタ・スタブをオプションでバインドできます。これにより、適切なSSL証明書を持つクライアントは、RMIレジストリに登録されたコネクタ・スタブを取得できます。RMIレジストリをSSLで保護するには、次のシステム・プロパティを設定する必要があります。

com.sun.management.jmxremote.registry.ssl=true

このプロパティがtrueに設定されている場合、Java VMの起動時に、すぐに使用できる管理エージェントによって、SSLで保護されたRMIレジストリの生成および構成が行われます。このプロパティのデフォルト値はfalseです。ただし、このプロパティはtrueに設定することをお薦めします。このプロパティがtrueに設定されている場合、全面的なセキュリティを施すため、SSLクライアント認証を有効にする必要もあります。

SSLクライアント認証の有効化

SSLクライアント認証を有効にするには、Java VMの起動時に次のシステム・プロパティを設定します。

com.sun.management.jmxremote.ssl.need.client.auth=true

クライアントSSL認証を使用するには、SSLを有効(デフォルトはfalseに設定されます)にしておく必要があります。このプロパティはtrueに設定することをお薦めします。この構成では、クライアント・システムが有効なデジタル証明書を持つ必要があります。「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が稼動しているシステムで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ファイルをアプリケーションに渡す必要があります。

パスワードとアクセス・ファイルの使用

パスワードおよびアクセス・ファイルは、リモート・モニタリングおよび管理のセキュリティを制御します。これらのファイルは、デフォルトではJAVA_HOME/conf/managementにあり、標準のJavaプロパティ・ファイル・フォーマットです。フォーマットに関する詳細は、java.util.Propertiesパッケージの「APIリファレンス」を参照してください。

パスワード・ファイル

パスワード・ファイルは、各種ロールとそのパスワードを定義します。アクセス制御ファイル(デフォルトでは、jmxremote.access)は、ロールごとに許可するアクセス権を定義します。ロールを機能させるには、パスワードとアクセス・ファイルの両方にエントリを持つ必要があります。

JDKには、jmxremote.password.templateというパスワード・ファイル・テンプレートがあります。このファイルをホーム・ディレクトリのJAVA_HOME/conf/management/jmxremote.passwordにコピーして、アクセス・ファイルで定義したロールのパスワードを追加します。

パスワード・ファイルにはパスワードがクリアテキストで含まれるため、必ず所有者だけがこのファイルへの読取りおよび書込みアクセス権を持つようにしてください。セキュリティ上の理由から、システムは所有者だけがファイルを読取り可能であるか確認し、そうでない場合はエラーとして終了します。このため、マルチユーザー環境では、パスワード・ファイルをホーム・ディレクトリなどの非公開の場所に保存する必要があります。

プロパティ名はロールで、関連付けられた値はロールのパスワードです。例2–1に、パスワード・ファイルのエントリの例を示します。

例 2-1パスワード・ファイルの例

# specify actual password instead of the text password
monitorRole password
controlRole password

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

JConsoleによるリモート・モニタリング(SSLが無効な場合)

SSLが無効な状態でリモート・アプリケーションをモニターするには、次のコマンドでJConsoleを起動します。

% jconsole hostName:portNum

ホスト名とポート番号を省略して、JConsoleが提供するダイアログ・ボックスに入力することもできます。

すぐに使用できるモニタリングと管理のプロパティ

すぐに使用できるモニタリングおよび管理のプロパティは、構成ファイルまたはコマンド行で設定できます。コマンド行で指定したプロパティにより、構成ファイル内のプロパティをオーバーライドします。構成ファイルのデフォルトの場所は、JAVA_HOME/conf/management/management.propertiesです。次のいずれかのコマンド行プロパティが設定されている場合、Java VMはこのファイルを読み取ります。

  • com.sun.management.jmxremote

    または
  • com.sun.management.jmxremote.port

次のコマンド行オプションで、構成ファイルに別の場所を指定できます。

com.sun.management.config.file=ConfigFilePath

ConfigFilePathは、構成ファイルへのパスです。

表2-1に、すぐに使用できるモニタリングおよび管理のプロパティを示します。

表2-1 すぐに使用できるモニタリングおよび管理のプロパティ

プロパティ 説明

com.sun.management.jmxremote

JMXコネクタを使用して、JMXリモート・エージェントおよびローカル・モニタリングを有効にします。このエージェントは、JConsoleおよび(Attach APIを使用する)その他のローカルJMXクライアントによって使用されるプライベート・インタフェースで公開されます。JConsoleがこのコネクタを使用できるのは、エージェントを起動したユーザーがそのコネクタも起動した場合です。このコネクタからの要求については、パスワードまたはアクセス・ファイルはチェックされません。

true / false.デフォルトはtrueです。

com.sun.management.jmxremote.port

JMXリモート・エージェントを有効にして、リモートJMXコネクタを作成し、指定したポートで待機します。デフォルトでは、SSL、パスワード、およびアクセス・ファイル・プロパティがこのコネクタに使用されます。また、com.sun.management.jmxremoteプロパティで説明したローカル・モニタリングも有効にします。

ポート番号。デフォルトなし。

com.sun.management.jmxremote.registry.ssl

RMIコネクタ・スタブを、SSLで保護された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に設定することをお薦めします。

true / false.デフォルトはfalseです。

com.sun.management.jmxremote.authenticate

このプロパティがfalseの場合、JMXでパスワードまたはアクセス・ファイルを使用できなくなります。すべてのユーザーに完全なアクセスが提供されます。

true / false.デフォルトはtrueです。

com.sun.management.jmxremote. password.file

パスワード・ファイルの場所を指定します。com.sun.management.jmxremote.authenticatefalseの場合、このプロパティならびにパスワードおよびアクセス・ファイルは無視されます。それ以外の場合は、パスワード・ファイルが存在し、有効な形式である必要があります。パスワード・ファイルが空であるか存在しない場合、アクセスは許可されません。

JAVA_HOME/conf/management/ jmxremote.password

com.sun.management.jmxremote.access.file

アクセス・ファイルの場所を指定します。com.sun.management.jmxremote.authenticateがfalseの場合、このプロパティ(ならびにパスワードおよびアクセス・ファイル)は無視されます。それ以外の場合は、アクセス・ファイルが存在し、有効な形式である必要があります。アクセス・ファイルが空であるか存在しない場合、アクセスは許可されません。

JAVA_HOME/conf/management/jmxremote.access

com.sun.management.jmxremote.login.config

JMXエージェントがユーザーを認証する場合に使用するJAAS (Java認証・承認サービス)ログイン構成エントリの名前を指定します。このプロパティを使用してデフォルトのログイン構成をオーバーライドする場合は、指定された構成エントリがJAASでロードされたファイルに存在する必要があります。また、構成で指定されたログイン・モジュールは、名前とパスワードのコールバックを使用してユーザーの資格証明を取得する必要があります。詳細は、javax.security.auth.callback.NameCallbackおよびjavax.security.auth.callback.PasswordCallbackのAPIドキュメントを参照してください。

デフォルトのログイン構成は、ファイルベースのパスワード認証です。

com.sun.management.jmxremote.rmi.port

RMIコネクタがバインドされるポート番号を指定します。

ポート番号。必ず未使用のポート番号を使用してください。

構成エラー

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); 

プログラムによるモニタリングおよび管理の設定

Attach APIを使用するJMXクライアントを作成することで、Java SE プラットフォームで起動する任意のアプリケーションに対して、すぐに使用できるモニタリングおよび管理を有効化できます。アプリケーションの起動時にモニター対象として構成する必要はありません。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) {
     vm.startLocalManagementAgent();

   // agent is started, get the connector address
   connectorAddress =
       vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);
}
// establish connection to connector server
JMXServiceURL url = new JMXServiceURL(connectorAddress);
JMXConnector 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エージェントに接続できます。

実行中のエージェントがない場合は、VirtualMachineクラスによってロードされます。そのコネクタ・アドレスはgetAgentProperties()メソッドによって取得されます。

次に、エージェントへの接続を確立するには、このコネクタ・アドレスから構築されたJMXサービスURLのJMXConnectorFactory.connectを呼び出します。

ノート:

JDK 11より前、Attach APIではDockerコンテナ内で実行されているJVMの検索で問題が発生していました。この問題は現在修正されており、jcmdおよびjpsは予想どおりに機能します。ただし、jmcでは、別のDockerコンテナで実行されているjavaプロセスをリストしません。javaプロセスのPIDをこのツールに明示的に指定する方法は不明です。

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構成の設定方法の詳細は、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スタックにより選択されます。リモート・オブジェクト(RMIServerRMIConnection)を指定されたポートにエクスポートするには、例2-5のように、プログラムによってRMIコネクタ・サーバーを作成する必要があります。ただし、JMXServiceURLは次のように指定する必要があります。

JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://localhost:" + 
      port1  + "/jndi/rmi://localhost:" + port2 + "/jmxrmi");

port1RMIServerおよびRMIConnectionリモート・オブジェクトがエクスポートされるポート番号、port2はRMIレジストリのポート番号です。

エージェント・クラスを使用するアプリケーションの計測

Java SEプラットフォームは、Javaプログラミング言語エージェントによりJava VMで実行中のプログラムを計測するサービスを提供します。インストゥルメンテーション・エージェントを作成すれば、アプリケーションをモニターする場合、そのアプリケーションに新しいコードを追加する必要がなくなります。モニタリングと管理は、アプリケーションのstatic mainメソッドに実装するのではなく、別のエージェント・クラスに実装し、-javaagentオプションを指定することでアプリケーションを起動します。エージェント・クラスを作成してアプリケーションを計測する方法の詳細は、java.lang.instrumentパッケージのAPIリファレンス・ドキュメントを参照してください。

アプリケーションを計測するエージェント・クラスの作成

次の手順は、com.example.MyAppのコードを改変して、エージェントにモニタリングおよび管理用の他のアプリケーションを計測させる方法を示しています。

  1. 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クラスとまったく同じです。

  2. com.example.MyAgentクラスをコンパイルします。
  3. Premain-Classエントリを使用して、マニフェスト・ファイルMANIFEST.MFを作成します。

    エージェントはJavaアーカイブ(JAR)ファイルとして配備されます。JARファイルに含まれるマニフェストの属性は、エージェントを起動するためにロードされるエージェント・クラスを指定します。MANIFEST.MFというファイルを作成し、次の行を挿入します。

    Premain-Class: com.example.MyAgent
    
  4. JARファイルMyAgent.jarを作成します。

    JARファイルには必ず次のファイルを入れます。

    • META-INF/MANIFEST.MF

    • com/example/MyAgent.class

  5. アプリケーションを起動し、モニタリングおよび管理サービスを提供するエージェントを指定します。

    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-5com.example.MyAppアプリケーションと同じコードを複製する場合、RMIコネクタ・サーバーはSSLで保護されているため、keystorepasswordの情報を指定します。