現在起動されている全てのVMのJMXローカルコネクタアドレスを取得する処理を、汎用的に使うために簡単な関数にした。
static final String CONNECTOR_ADDRESS
= "com.sun.management.jmxremote.localConnectorAddress";
public static String[] getJMXLocalConnectorAddresses() throws IOException {
List<String> addresses = new ArrayList<String>();
for (VirtualMachineDescriptor desc : VirtualMachine.list()) {
try {
VirtualMachine vm = VirtualMachine.attach(desc.id());
String connectorAddress;
try {
//ローカルコネクタアドレスが格納されているプロパティを取得
connectorAddress =
vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);
//コネクタアドレスが空の場合、エージェントのロードを試みる(まだロードされていない可能性がある)
if (connectorAddress == null) {
try {
String agent =
vm.getSystemProperties().getProperty("java.home")
+ File.separator + "lib" + File.separator
+ "management-agent.jar";
vm.loadAgent(agent);
//起動したエージェントからローカルコネクタアドレスを取得
connectorAddress =
vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);
} catch (AgentLoadExeption e) {
connectorAddress = null;
} catch (AgentInitializationException e) {
connectorAddress = null;
}
}
} finally {
vm.detach();
}
if ( !connectorAddress.isEmpty() ) {
addresses.add(connectorAddress);
}
} catch (AttachNotSupportedException e) {
continue;
}
}
return addresses.toArray(new String[]{});
}それにしても長い...もっとすっきり書けないものか。
にしても、これでやっと
・サーバアプリケーションは起動後、サーバソケットをリスン状態にしてポートを番号をMXBeanに公開する
・クライアントアプリケーションは現在起動されている任意のVMからMXBean(への参照)を取得する
・サーバが起動されていない(MXBeanが一つも見つからない)のであればサーバアプリケーションを起動する
・公開されているコードベースとポートを使って任意のサーバに接続して通信を開始する
という、プチ自律なプロセス間通信を実現できるようになった訳だ。
JMX(MXBean)は同一PC上に限れば作るのも管理するのも、難しくないのでいろいろと応用が効きそうである。