- PR -

プラットフォームMBeanサーバのマニュアル起動

投稿者投稿内容
カーニー
ぬし
会議室デビュー日: 2003/09/04
投稿数: 358
お住まい・勤務地: 東京
投稿日時: 2007-02-08 13:22
Sun Java SE 6ベースで開発しています。
JVM起動時にプラットフォームMBeanサーバを自動起動し、指定ポート経由でのアクセスを許可するためには、(最低限)以下のJVM起動オプションが必要です。

-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.port=<ポート番号>

さて、このポート番号をJVM起動後に決定したいのですが、それは可能でしょうか?
つまり自動起動は行わず、プログラム内でポート番号決定後にプラットフォームMBeanサーバをマニュアル起動したいのです。

試しに-Dcom.sun.management.jmxremote=falseで起動し、以下のようなコードを実行してみましたが指定ポートでのリスンは始まりませんでした。

System.setProperty("com.sun.management.jmxremote.port=<ポート番号>");
ManagementFactory.getPlatformMBeanServer();

何かヒントなどあれば、ぜひ教えてください。よろしくお願いします。
さくらば
大ベテラン
会議室デビュー日: 2002/11/12
投稿数: 145
投稿日時: 2007-02-08 15:01
こんにちは、さくらばです。

引用:

さて、このポート番号をJVM起動後に決定したいのですが、それは可能でしょうか?
つまり自動起動は行わず、プログラム内でポート番号決定後にプラットフォームMBeanサーバをマニュアル起動したいのです。

試しに-Dcom.sun.management.jmxremote=falseで起動し、以下のようなコードを実行してみましたが指定ポートでのリスンは始まりませんでした。

System.setProperty("com.sun.management.jmxremote.port=<ポート番号>");
ManagementFactory.getPlatformMBeanServer();



ManagementFactory.getPlatformMBeanServer で取得した MBeanServer は通信の
ための設定はしてありません。通信を行うためには MBeanServer に Connector
を追加します。

コード:
    MBeanServer server = ManagementFactory.getPlatformMBeanServer();

    JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" 
+ hostname + ":" + port + "/jmxrmi");
    connector = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server);
    connector.start();



ただし、これだけだと RMI で通信できないので、別途 rmiregistry を指定のポート
で立ち上げておく必要があります。プログラムの中で rmiregistry を起動すること
もできます。

プログラムが起動した後に、JMX をプログラムの外部から起動させたいので
あれば、Attach API が使えます。

http://itpro.nikkeibp.co.jp/article/COLUMN/20061208/256374/?ST=develop
カーニー
ぬし
会議室デビュー日: 2003/09/04
投稿数: 358
お住まい・勤務地: 東京
投稿日時: 2007-02-08 16:49
さくらばさん

ご回答、どうもありがとうございます。
おかげさまでrmiregistryを別途起動する方法で、ひとまずプログラムからリスンを開始することができました。

引用:

さくらばさんの書き込み (2007-02-08 15:01) より:
ただし、これだけだと RMI で通信できないので、別途 rmiregistry を指定のポート
で立ち上げておく必要があります。プログラムの中で rmiregistry を起動すること
もできます。



さて、今度はrmiregistryの起動に挑戦してみますが、一点だけ確認させて下さい。
これは今回Connectorを追加したプログラムの中で、事前にrmiregistryを起動しておくという理解で正しいのでしょうか?
参照先URLの以下の記述を読むと、マネージャ(jconsole)側で起動しているようにも受け取れるのですが・・・。
引用:

JMX Remoteは通信にRMIを使用するので,事前にrmiregistryを実行しておく必要があります。えっ,jconsoleを使うときはrmiregistryなんか実行しないよ,と思われる方も多いでしょう。

そうなんです。rmiregistryはアプリケーション中で実行させることもできるのです。しかし,ここでは簡単化のために省略しました。

興味のある方は,sun.management.Agentクラスを調べてみてください。このクラスがjconsoleによってロードされるエージェントです。

カーニー
ぬし
会議室デビュー日: 2003/09/04
投稿数: 358
お住まい・勤務地: 東京
投稿日時: 2007-02-08 17:20
さくらばさんにいただいたヒントを元に、sun.management.Agentクラスのソースを追ったら、あっさりできてしまいました。

コード:
System.setProperty("com.sun.management.jmxremote", "true");
System.setProperty("com.sun.management.jmxremote.port", "8599");
Agent.startAgent();



これだけです。まあ、思いっきりSunのJVMに依存しているわけですが、運良くサポートしないといけないOSはLinux/Windows/Solarisだけなのです。

さくらばさん、本当にどうもありがとうございました。
カーニー
ぬし
会議室デビュー日: 2003/09/04
投稿数: 358
お住まい・勤務地: 東京
投稿日時: 2007-02-08 17:47
補足です。

当たり前と言えば当たり前なのですが、プラットフォームMBeanサーバーは二重起動ができません。
なので、先述の方法でプラットフォームMBeanサーバーを起動する際は、Java起動オプションに"-Dcom.sun.management.jmxremote"を指定してはいけません。trueでもfalseでもダメで、無指定が正解です。

以上、ご参考まで。(こんなことやる人はそうそういないと思いますが・・・)
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-02-09 01:28
プログラムからrmiregistryを起動するには、
java.rmi.registry.LocateRegistry#getRegistry()でできますよ。
既に同じポートで動いていたら怒られると思いましたが。
古い記憶で申し訳ないですが・・・

わたしもカーニーさんと同じようなプログラムを作っていますよ。
分散環境でTomcat5.5を使っているのですが、
マネージャアプリの代わりにJConsoleで管理できるようにしています。
(極限まで機能を削ぎ落としたTomcatにしている)

サーブレットの中でPlatformMBeanServerを取得すると、
Tomcatの管理アプリで操作可能な情報がJConsoleに現れます。
なので、コネクタサーバ+rmiregistryで外部から管理できるようにしています。

そして割と重要なんですが、待ち受けのJMXServiceURLをログにダンプして、
いざ待ち受けのURLがわからない、ということがないようにしています。

MBeanって結構便利なのですが、意外と使われていませんね。
簡単にリモート処理ができるフレームワークと割り切ると、
これほど楽なものはないのでは?と思います。

そういやシェルで対話式で管理できるクライアントってないのでしょうかね。
Jaune
会議室デビュー日: 2006/12/02
投稿数: 16
投稿日時: 2007-02-09 02:16
こんばんは。
ご参考までに、自分は以下のようなやり方をしています。

コード:
int port = 1099;
String hostName = "localhost";
String bindName = "jmxrmi";

String url = "service:jmx:rmi:///jndi/rmi://" + hostName + ":" + port + "/" + bindName;

java.rmi.registry.LocateRegistry.createRegistry(port);
MBeanServer server = ManagementFactory.getPlatformMBeanServer();

JMXServiceURL serviceUrl = new JMXServiceURL(url);
JMXConnectorServer connector = JMXConnectorServerFactory.newJMXConnectorServer(serviceUrl, null, server);
connector.start();



と書いているうちに、かつのりさんとかぶってしまいましたか…(^^;)
引用:
かつのりさんの書き込み (2007-02-09 01:28) より:

MBeanって結構便利なのですが、意外と使われていませんね。
簡単にリモート処理ができるフレームワークと割り切ると、
これほど楽なものはないのでは?と思います。


同感です。
C/S 構成の簡単なアプリを組む時に使ってみたのですが、自分で通信やソケット周りの部分をごりごり書かなくて済むのですごく楽でした。
カーニー
ぬし
会議室デビュー日: 2003/09/04
投稿数: 358
お住まい・勤務地: 東京
投稿日時: 2007-02-13 11:58
かつのりさん、Jauneさん

情報どうもありがとうございます。週末を挟んでお礼が遅くなってしまいました。

教えていただいた方法は標準APIですからとてもよいですね。
やってみたところ問題なくできました。

が、プログラムが停止しない・・・・・non-daemonスレッドがあがってしまったからかな?
追って報告します。

スキルアップ/キャリアアップ(JOB@IT)