目次 | 前へ | 次へ | Java Management Extensions (JMX) テクノロジのチュートリアル |
この章では、標準および動的な管理 Bean (MBean) の概念を紹介します。また、Java Management Extensions (JMX) テクノロジを使用して MBean 上でローカルおよびリモートから操作を実行する方法について示します。
この例では、標準および動的 MBeans のみを説明します。
第 2 章「JMX API の基本要素」で説明したように、標準 MBean は内部のメソッドの名前を使用して管理インタフェースを静的に定義する管理 Bean です。動的 MBean は、特定の Java インタフェースを実装し、実行時に自らの属性と操作を示します。
JMX テクノロジは、RMI に基づいてコネクタを定義します。RMI コネクタは、Java Remote Method Protocol (JRMP) と Internet Inter-Object Request Broker (ORB) Protocol (IIOP) の 2 つの標準 RMI トランスポートをサポートしています。このコネクタを使用すると、MBean サーバーの MBean にリモート接続し、ローカルで操作を実行するのとまったく同じように、その MBean で操作を実行できます。
この例は、標準 MBean と動的 MBean の実装を説明することを目的としています。また、両 MBean 上でローカルに、またサーバーとリモートクライアント間の RMI 接続を通じてリモートに操作を実行する方法も示します。
この例を実行する場合
SimpleStandard
と SimpleDynamic
の MBean を登録RMI コネクタの例は、ディレクトリ work_dir/jmx_examples/Basic
内にあります。
次のセクションでは、基本的な MBean の例題で使用される各クラスを分析し、各クラスがこれまでのセクションで説明した操作をどのように実行するかについて説明します。
Server.java
クラスは、その大きさにより、いくつかのコード (抜粋) で現れます。
public class Server { public static void main(String[] args) { try { MBeanServer mbs = MBeanServerFactory.createMBeanServer(); waitForEnterPressed(); String domain = mbs.getDefaultDomain(); waitForEnterPressed(); String mbeanClassName = "SimpleStandard"; String mbeanObjectNameStr = domain + ":type=" + mbeanClassName + ",name=1"; ObjectName mbeanObjectName = createSimpleMBean(mbs, mbeanClassName, mbeanObjectNameStr); waitForEnterPressed(); printMBeanInfo(mbs, mbeanObjectName, mbeanClassName); waitForEnterPressed(); manageSimpleMBean(mbs, mbeanObjectName, mbeanClassName); waitForEnterPressed(); mbeanClassName = "SimpleDynamic"; mbeanObjectNameStr = domain + ":type=" + mbeanClassName + ",name=1"; mbeanObjectName = createSimpleMBean(mbs, mbeanClassName, mbeanObjectNameStr); waitForEnterPressed(); printMBeanInfo(mbs, mbeanObjectName, mbeanClassName); waitForEnterPressed(); manageSimpleMBean(mbs, mbeanObjectName, mbeanClassName); waitForEnterPressed(); [...]
このクラスを検討すると、次のイベントが起こっていることがわかります。
まず、Server.java
クラスは、MBeanServerFactory
クラスの createMBeanServer()
メソッドを呼び出して mbs
と呼ばれる新しい MBean サーバーを作成します。
次に MBean サーバーを登録するデフォルトドメインを、MBeanServer
インタフェースの getDefaultDomain()
メソッドを呼び出して取得します。このドメインは、文字列 domain
で識別されます。
MBean クラス SimpleStandard
も、この場合は文字列 mbeanClassName
という変数により識別されます。SimpleStandard
は、この MBean をインスタンスとする Java オブジェクトの Java クラスの名前です。SimpleStandard.java
オブジェクトについては、セクション「SimpleStandard.java」を参照してください。
もう 1 つの変数、文字列 mbeanObjectNameStr
は、ドメインと次のキー=値ペアを組み合わせて定義されます。
mbeanObjectNameStr
の目的は、人間が読むことができる識別子を MBean に割り当てることです。
createSimpleMBean() の呼び出しにより、指定されたオブジェクト名の SimpleStandard MBean がローカル MBean サーバーで作成され、登録されます。
次に、printMBeanInfo()
と manageSimpleMBean()
の両方の操作が、SimpleStandard
MBean で実行されます。createSimpleMBean()
と同様、これらのメソッドはあとで Server.java
コードで定義され、コード例 3-4 とコード例 3-5 で示されます。
このコードには記述されていませんが、SimpleDynamic
型の 2 番目の MBean が、SimpleStandard
MBean とまったく同じ方法で MBean サーバーに作成され、登録されます。その名前が示すように、この MBean はセクション「SimpleDynamic.java」で説明する SimpleDynamic
Java オブジェクトのインスタンスです。
[...] JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/server"); JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); cs.start(); waitForEnterPressed(); cs.stop(); [...]
コード例 3-2 では、RMI コネクタサーバーは MBean でリモート操作ができるように作成されています。JMXServiceURL
クラスを呼び出すと、コネクタサーバーのアドレスとなる url
という新しいサービス URL が作成されます。この例では、サービス URL はエンコード形式ではなく JNDI 形式で指定されます (JNDI 形式の詳細は、javax.management.remote.rmi
パッケージの API ドキュメントを参照)。このサービス URL は、次の内容を定義しています。
rmi
で表されるデフォルトの RMI トランスポートを使用する。9999
で稼動し、サーバーアドレスは server
の名前で登録される。例で指定されるポート 9999
は任意の数字。使用可能なポートを指定できる。RMI コネクタサーバー cs
は、パラメータにサービス URL url
、null
環境マップ、および MBean サーバー mbs
を使用して、コンストラクタ JMXConnectorServerFactory
を呼び出して作成されます。コネクタサーバー cs
は、JMXConnectorServer
の start()
メソッドを呼び出し、RMIConnectorServer
が RMI オブジェクト server
を RMI レジストリにエクスポートすることで起動されます。この接続は、Enter キーを押すまで有効です。これは Server
コードの後半で定義する簡単なメソッド waitForEnterPressed
の手順に従ったものです。
[...] private static ObjectName createSimpleMBean(MBeanServer mbs, String mbeanClassName, String mbeanObjectNameStr) { echo("\n>>> Create the " + mbeanClassName + " MBean within the MBeanServer"); echo("ObjectName = " + mbeanObjectNameStr); try { ObjectName mbeanObjectName = ObjectName.getInstance(mbeanObjectNameStr); mbs.createMBean(mbeanClassName, mbeanObjectName); return mbeanObjectName; } catch (Exception e) { echo( "!!! Could not create the " + mbeanClassName + " MBean !!!"); e.printStackTrace(); echo("\nEXITING...\n"); System.exit(1); } return null; } [...]
コード例 3-3 は、createSimpleMBean()
メソッドの定義を示しています。このメソッドでは、オブジェクト名 mbeanObjectNameStr
を使用した MBean インスタンスが、ObjectName
インタフェースの getInstance()
メソッドに渡され、MBean サーバー内で MBean に登録するための新しいオブジェクト名が作成されます。最終的なオブジェクト名インスタンスは、mbeanObjectName
に設定されます。次に MBeanServer
のメソッド createMBean()
により、mbeanClassName
で識別される Java オブジェクトと MBean インスタンス mbeanObjectName
の組み合わせにより MBean のインスタンスが作成され、MBean サーバー mbs
にこの MBean が登録されます。
[...] private static void printMBeanInfo(MBeanServer mbs, ObjectName mbeanObjectName, String mbeanClassName) { MBeanInfo info = null; try { info = mbs.getMBeanInfo(mbeanObjectName); } catch (Exception e) { echo( "!!! Could not get MBeanInfo object for " + mbeanClassName +" !!!"); e.printStackTrace(); return; } MBeanAttributeInfo[] attrInfo = info.getAttributes(); if (attrInfo.length > 0) { for (int i = 0; i < attrInfo.length; i++) { echo(" ** NAME: " + attrInfo[i].getName()); echo(" DESCR: " + attrInfo[i].getDescription()); echo(" TYPE: " + attrInfo[i].getType() + "READ: "+ attrInfo[i].isReadable() + "WRITE: "+ attrInfo[i].isWritable()); } } else echo(" ** No attributes **"); [...]
コード例 3-4 は、メソッド printMBeanInfo()
の定義を示しています。printMBeanInfo()
メソッドは MBeanServer
のメソッド getMBeanInfo()
を呼び出して、MBean mbeanObjectName
により開示される属性と操作の詳細を取得します。MBeanAttributeInfo
は次のメソッドを定義します。それらのメソッドはそれぞれ、mbeanObjectName
MBean の属性に関する情報を取得する場合に呼び出されます。
getName
。属性の名前を取得する。getDescription
。人間が読むことのできる属性の説明を取得する。getType
。属性のクラス名を取得する。isReadable
。属性が読み出し可能か否かを判断する。isWritable
。属性が書き込み可能かどうかを判断する。ここには示していませんが、呼び出しが行われるのは、mbeanObjectName
MBean のコンストラクタ、操作、および通知に関する情報を取得するためです。
MBeanConstructorInfo
。MBean の Java クラスに関する情報を取得する。MBeanOperationInfo
。MBean で実行される操作の内容、MBean で使われるパラメータの種類を学習する。MBeanNotificationInfo
。MBean の操作が実行された場合に、MBean から送信される通知の種類を調べる。[...] private static void manageSimpleMBean(MBeanServer mbs, ObjectName mbeanObjectName, String mbeanClassName) { try { printSimpleAttributes(mbs, mbeanObjectName); Attribute stateAttribute = new Attribute("State", "new state"); mbs.setAttribute(mbeanObjectName, stateAttribute); printSimpleAttributes(mbs, mbeanObjectName); echo("\n Invoking reset operation..."); mbs.invoke(mbeanObjectName, "reset", null, null); printSimpleAttributes(mbs, mbeanObjectName); } catch (Exception e) { e.printStackTrace(); } } private static void printSimpleAttributes( MBeanServer mbs, ObjectName mbeanObjectName) { try { String State = (String) mbs.getAttribute(mbeanObjectName, "State"); Integer NbChanges = (Integer) mbs.getAttribute(mbeanObjectName, "NbChanges"); } catch (Exception e) { echo( "!!! Could not read attributes !!!"); e.printStackTrace(); } } [...]
コード例 3-5 は簡単な MBean を管理するためのメソッドを示しています。
まず、manageSimpleMBean()
メソッドが、Server
でも定義される printSimpleAttributes()
メソッドを呼び出します。printSimpleAttributes()
メソッドは、MBean mbeanObjectName
から state
という MBean 属性と、NbChanges
というもう 1 つの MBean 属性を取得します。これらの属性はいずれも、セクション「SimpleStandard.java」に示すように、SimpleStandard
クラスで定義されます。
次に manageSimpleMBean()
メソッドは、Attribute
クラスのインスタンスである属性 stateAttribute
を定義します。stateAttribute
属性は、値 new state
を SimpleStandard
で定義される既存の属性 state
に関連付けます。次に MBeanServer
の setAttribute()
メソッドに呼び出すことで、mbeanObjectName
MBean の状態が stateAttribute
で定義される新しい状態に設定されます。
最後に MBeanServer
の invoke()
メソッドに呼び出すことで、mbeanObjectName
MBean の reset
操作が起動します。reset
操作は、SimpleStandard
クラスで定義されます。
SimpleStandardMBean.java
クラスをコード例 3-1 に示します。
public interface SimpleStandardMBean { public String getState(); public void setState(String s); public int getNbChanges(); public void reset(); }
SimpleStandardMBean.java
クラスは、MBean SimpleStandard
の簡単な JMX 仕様の管理インタフェースです。このインタフェースは、JMX エージェントからの管理のために SimpleStandard
で定義された 4 つの操作を公開します。
SimpleStandard.java
クラスをコード例 3-1 に示します。
public class SimpleStandard extends NotificationBroadcasterSupport implements SimpleStandardMBean { public String getState() { return state; } public void setState(String s) { state = s; nbChanges++; } public int getNbChanges() { return nbChanges; } public void reset() { AttributeChangeNotification acn = new AttributeChangeNotification(this, 0, 0, "NbChanges reset", "NbChanges", "Integer", new Integer(nbChanges), new Integer(0)); state = "initial state"; nbChanges = 0; nbResets++; sendNotification(acn); } public int getNbResets() { return nbResets; } public MBeanNotificationInfo[] getNotificationInfo() { return new MBeanNotificationInfo[] { new MBeanNotificationInfo( new String[] { AttributeChangeNotification.ATTRIBUTE_CHANGE }, AttributeChangeNotification.class.getName(), "This notification is emitted when the reset() method is called.") }; } private String state = "initial state"; private int nbChanges = 0; private int nbResets = 0; }
SimpleStandard
クラスは、簡単な JMX 仕様の標準 MBean を定義します。
SimpleStandard
MBean は、セクション「SimpleStandardMBean.java」に示すように、対応する SimpleStandardMBean
インタフェースを実装することで、管理のための操作と属性を開示します。
この MBean で開示される簡単な操作を次に示します。
リセット操作により発行される通知は、クラス AttributeChangeNotification
のインスタンスであり、リセットの呼び出し前に State
属性で実行された変更数に関する情報を収集します。送信される通知の内容は、MBeanNotificationInfo
インスタンスで定義されます。
SimpleDynamic
クラスをコード例 3-1 に示します。
public class SimpleDynamic extends NotificationBroadcasterSupport implements DynamicMBean { public SimpleDynamic() { buildDynamicMBeanInfo(); } [...]
SimpleDynamic
の動的 MBean では、DynamicMBean
インタフェースを実装することで、実行時に管理用の属性と操作を開示する方法を示します。ここでは、まず、MBean に関する情報を動的に取得するためのメソッド buildDynamicMBeanInfo()
の定義から開始します。buildDynamicMBeanInfo()
メソッドは、動的 MBean に MBeanInfo
を構築します。
SimpleDynamic
のほかのコードは、DynamicMBean
インタフェースの実装に対応しています。開示される属性、操作、通知は、SimpleStandard
MBean で開示されるものと同じです。
ClientListener.java
クラスをコード例 3-1 に示します。
public class ClientListener implements NotificationListener { public void handleNotification(Notification notification, Object handback) { System.out.println("\nReceived notification: " + notification); } }
ClientListener
クラスは、簡単な JMX 仕様の通知リスナを実装します。
通知が受領されると、NotificationListener
インタフェースの handleNotification()
メソッドが呼び出され、通知の受領を確認するためのメッセージが出力されます。
Client.java
クラスをコード例 3-1 に示します。
public class Client { public static void main(String[] args) { try { // Create an RMI connector client // JMXServiceURL url = new JMXServiceURL( "service:jmx:rmi:///jndi/rmi://localhost:9999/server"); JMXConnector jmxc = JMXConnectorFactory.connect(url, null); ClientListener listener = new ClientListener(); MBeanServerConnection mbsc = jmxc.getMBeanServerConnection(); waitForEnterPressed(); // Get domains from MBeanServer // String domains[] = mbsc.getDomains(); for (int i = 0; i < domains.length; i++) { System.out.println("Domain[" + i + "] = " + domains[i]); } waitForEnterPressed(); String domain = mbsc.getDefaultDomain(); // Create SimpleStandard MBean ObjectName mbeanName = new ObjectName(domain +":type=SimpleStandard,name=2"); mbsc.createMBean("SimpleStandard", stdMBeanName, null, null); waitForEnterPressed(); // Create SimpleDynamic MBean ObjectName dynMBeanName = new ObjectName(domain +":type=SimpleDynamic,name=2"); echo("\nCreate SimpleDynamic MBean..."); mbsc.createMBean("SimpleDynamic", dynMBeanName, null, null); waitForEnterPressed(); // Get MBean count echo("\nMBean count = " + mbsc.getMBeanCount()); // Query MBean names echo("\nQuery MBeanServer MBeans:"); Set names = mbsc.queryNames(null, null); for (Iterator i = names.iterator(); i.hasNext(); ) { echo( "ObjectName = " + (ObjectName) i.next()); } waitForEnterPressed(); mbsc.setAttribute(stdMBeanName, new Attribute("State", "changed state")); SimpleStandardMBean proxy = JMX.newMBeanProxy( mbsc, stdMBeanName, SimpleStandardMBean.class, true); echo("\nState = " + proxy.getState()); ClientListener listener = new ClientListener(); mbsc.addNotificationListener(stdMBeanName, listener, null, null); mbsc.invoke(stdMBeanName, "reset", null, null); mbsc.removeNotificationListener(stdMBeanName, listener); mbsc.unregisterMBean(stdMBeanName); [...] jmxc.close(); } catch (Exception e) { e.printStackTrace(); } } } [...]
Client.java
クラスは、RMI コネクタクライアントを作成します。このクライアントは、Server.java
で作成される RMI コネクタサーバーへの接続用に構成されます。
Client.java
は Server.java
で定義されるのと同じサービス URL、url
を定義します。これによって、コネクタクライアントは、ローカルホストのポート 9999
で動作する RMI レジストリから RMI コネクタサーバースタブ server
を取得し、RMI コネクタサーバーに接続することができます。
RMI レジストリがこのように特定された場合、コネクタクライアントを作成できます。コネクタクライアント jmxc
は、JMXConnectorFactory
の connect()
メソッドにより作成されたインタフェース JMXConnector
のインスタンスです。connect()
メソッドは、呼び出されると、パラメータ url
と null
環境マップが渡されます。
またクライアントは、セクション「ClientListener.java」に示すように、ClientListener
のインスタンスを作成して通知を待機します。
次に、JMXConnector
インスタンス jmxc
の getMBeanServerConnection()
メソッドを呼び出して、JMX 仕様 MBeanServerConnection
のインスタンス mbsc
が作成されます。
これによってコネクタクライアントは Server.java
で作成された MBean サーバーに接続され、両端への接続が完全に透過的な状態にあれば MBean の登録と MBean での操作が可能になります。
クライアントは、MBeanServerConnection
の createMBean()
メソッドを呼び出して、MBean サーバーに SimpleStandard
MBean と SimpleDynamic MBean を作成および登録します。そして、SimpleStandard
と SimpleDynamic
で定義された操作を、ローカル JMX 仕様の MBean 操作とまったく同様に実行します。
MBean プロキシにより Java インタフェースを介して MBean にアクセスできるため、長いコードを記述しなくても、プロキシ上で呼び出してリモート MBean にアクセスできます。SimpleStandardMBean
の MBean プロキシをここで作成するには、javax.management.JMX
クラスの newMBeanProxy()
メソッドを呼び出し、MBean の MBeanServerConnection
、オブジェクト名、MBean インタフェースのクラス名、および true を渡して、このプロキシが NotificationBroadcaster
として動作する必要があることを知らせます。MXBean のプロキシを標準 MBean の場合とまったく同じ方法で作成するには、newMBeanProxy()
ではなく newMXBeanProxy()
を呼び出します。
SimpleDynamic
で実行される各操作は、SimpleStandard
で実行されるものと同じであるため、ここでは操作のコードを記載していません。
最後に、クライアントは SimpleStandard
MBean の登録を解除し、接続を終了します。最後の removeNotificationListener
はオプションです。これはリモートクライアントで登録されたリスナは、そのクライアントの終了時に削除されるためです。
クラスの例題を検証したあと、今度は例題を実行します。例を実行するには、次の手順に従うか、README
ファイルを参照します。
$
javac *.java
9999
で RMI レジストリを起動します。
RMI レジストリは、Server
によって RMI コネクタスタブの登録に使用されます。
$
rmiregistry 9999 &
Server
クラスを起動します。
$
java -classpath .Server
MBean サーバーの作成、および MBean サーバーでの SimpleStandard
MBean の作成を確認するプロンプトが表示されます。次に SimpleStandard
MBean に関する情報を取得し、この MBean で操作を実行する場合は、Enter キーを押すように要求されます。
SimpleStandard
での操作が終了すると、SimpleDynamic
MBean について、同じプロセスが繰り返されます。
標準および動的 MBean が作成され、各 MBean 上での操作が実行されたあと、RMI コネクタサーバーの作成が表示されます。このサーバーを使用すると、リモート Client
から MBeans 上で操作を実行できます。
Client
クラスを起動します。
$
java -classpath .Client
RMI コネクタの作成、およびコネクタサーバーとの接続の作成の確認が表示されます。ドメイン名と、SimpleStandard
および SimpleDynamic の MBean の作成と登録についても通知されます。クライアントは次に、SimpleStandard
と SimpleDynamic の両 MBean で操作を実行し、その後、両 MBean の登録を解除します。