Binding JMX on a dedicated address
Unfortunately in order to get JMX to bind to dedicated address (and not just 0.0.0.0) you have to jump through a few hoops. In order to save you some time - here is how you do it. Create your own RMISocketFactory that only creates server sockets on the specified address
public class RMIServerSocketFactoryImpl implements RMIServerSocketFactory {
private final InetAddress localAddress;
public RMIServerSocketFactoryImpl( final InetAddress pAddress ) {
localAddress = pAddress;
}
public ServerSocket createServerSocket(final int pPort) throws IOException {
return ServerSocketFactory.getDefault()
.createServerSocket(pPort, 0, localAddress);
}
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
return obj.getClass().equals(getClass());
}
public int hashCode() {
return RMIServerSocketFactoryImpl.class.hashCode();
}
}
Then create the naming service with that factory and create the RMI server using that naming service.
RMIServerSocketFactory serverFactory = new RMIServerSocketFactoryImpl(InetAddress.getByName(address));
LocateRegistry.createRegistry(namingPort, null, serverFactory);
StringBuffer url = new StringBuffer();
url.append("service:jmx:");
url.append("rmi://").append(address).append(':').append(protocolPort).append("/jndi/");
url.append("rmi://").append(address).append(':').append(namingPort).append("/connector");
Map env = new HashMap();
env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, serverFactory);
rmiServer = new RMIConnectorServer(
new JMXServiceURL(url.toString()),
env,
ManagementFactory.getPlatformMBeanServer()
);
rmiServer.start();
Why do some so simple things need to be so overly complicated?
As if that were not complicated enough, you also have to set the java.rmi.server.hostname property to be sure it will work. See http://weblogs.java.net/blog/emcmanus/archive/2006/12/multihomed_comp.html and blame it all on RMI.