2013-7-11 15:58:05 ClientCommunicatorAdmin restart 警告: Failed to restart: java.io.IOException: Failed to get a RMI stub: javax.naming.ServiceUnavailableException [Root exception is java.rmi.ConnectException: Connection refused to host: 10.10.4.18; nested exception is: java.net.ConnectException: Connection refused: connect] 2013-7-11 15:58:06 RMIConnector RMIClientCommunicatorAdmin-doStop 警告: Failed to call the method close():java.rmi.ConnectException: Connection refused to host: 10.10.4.18; nested exception is: java.net.ConnectException: Connection refused: connect 2013-7-11 15:58:06 ClientCommunicatorAdmin Checker-run 警告: Failed to check connection: java.net.ConnectException: Connection refused: connect 2013-7-11 15:58:06 ClientCommunicatorAdmin Checker-run
但具体解决方式却不是显而易见的。Google了好长时间,大部分都提到了使用完Socket要及时关闭之类的,并不相关。
我大大致分析了java代码后,解决了该问题。
分析过程如下:
我们一般创建一个MBeanServerConnection的过程
JMXServiceURL serviceurl = new JMXServiceURL(url); JMXConnector conn = JMXConnectorFactory.connect(serviceurl, null); MBeanServerConnection mbsc = conn .getMBeanServerConnection();
此时可以用mbsc来获取相应的属性值,执行相应的方法等。但如果此时远程MBeanServer关闭了,不久就会抛出上面的异常。该异常是不受代码控制的,也就是try,catch并不能捕获。
而如果要屏蔽掉异常信息,只能从java代码入手分析。
我们在创建一个JMXConnector时使用如下方式:
JMXConnector conn = JMXConnectorFactory.connect(serviceurl, null);
此时,第二个参数可以指定一些环境信息。
当JMXConnector为RMI的时候,RMI的connect方法中有如下代码:
final long checkPeriod = EnvHelp.getConnectionCheckPeriod(usemap); communicatorAdmin = new RMIClientCommunicatorAdmin(checkPeriod); public RMIClientCommunicatorAdmin(long period) { super(period); } 其super方法调用: public ClientCommunicatorAdmin(long period) { this.period = period; if (period > 0) { checker = new Checker(); Thread t = new Thread(checker); t.setDaemon(true); t.start(); } else checker = null; }
从上面的代码可以看出,RMIConnector的connect方法中会创建一个RMIClientCommunicatorAdmin,该类会根据传入的env创建一个Checker,用来检测MBeanServer和Client的心跳。
其默认值
public static long getConnectionCheckPeriod(Map env) { return getIntegerAttribute(env, CLIENT_CONNECTION_CHECK_PERIOD, 60000L, 0, Long.MAX_VALUE); }
大于0,所以Checker会成功创建。
通过以上分析,如果我们不需要Checker,只需要在创建Connector的时候提供env,设置相应的属性值不大于0就可以了。
所以改成如下创建方式:
JMXServiceURL serviceurl = new JMXServiceURL(url); Map m = new HashMap(); m.put("jmx.remote.x.client.connection.check.period", 0L); conn = JMXConnectorFactory.connect(serviceurl, m); MBeanServerConnection mbsc = conn .getMBeanServerConnection();
即可成功屏蔽开头提到的异常信息。