客户端: Windows XP SP3,JDK 1.5.0_14;服务端:CentOS 5.4 Final(Rad Hat版本:5.1.19.6,linux核心:2.6.18-164.el5),JDK 1.6.0_21 for linux。
开始时,在Windows环境下,使用“jconsole”,连接CentOS下的一个Java服务,在命令行连续不断的抛出以下异常信息:
- 2010-7-26 11:06:25 com.sun.corba.se.impl.transport.SocketOrChannelConnectionImpl
- <init>
- 警告: "IOP00410201: (COMM_FAILURE) Connection failure: socketType: IIOP_CLEAR_TE
- XT; hostname: 127.0.0.1; port: 6888"
- org.omg.CORBA.COMM_FAILURE: vmcid: SUN minor code: 201 completed: No
- at com.sun.corba.se.impl.logging.ORBUtilSystemException.connectFailure(O
- RBUtilSystemException.java:2172)
- at com.sun.corba.se.impl.logging.ORBUtilSystemException.connectFailure(O
- RBUtilSystemException.java:2193)
- at com.sun.corba.se.impl.transport.SocketOrChannelConnectionImpl.<init>(
- SocketOrChannelConnectionImpl.java:205)
- at com.sun.corba.se.impl.transport.SocketOrChannelConnectionImpl.<init>(
- SocketOrChannelConnectionImpl.java:218)
- at com.sun.corba.se.impl.transport.SocketOrChannelContactInfoImpl.create
- Connection(SocketOrChannelContactInfoImpl.java:101)
- at com.sun.corba.se.impl.protocol.CorbaClientRequestDispatcherImpl.begin
- Request(CorbaClientRequestDispatcherImpl.java:152)
- at com.sun.corba.se.impl.protocol.CorbaClientDelegateImpl.request(CorbaC
- lientDelegateImpl.java:118)
- at com.sun.corba.se.impl.protocol.CorbaClientDelegateImpl.is_a(CorbaClie
- ntDelegateImpl.java:211)
- at com.sun.corba.se.impl.protocol.CorbaClientDelegateImpl.is_a(CorbaClie
- ntDelegateImpl.java:221)
- at org.omg.CORBA.portable.ObjectImpl._is_a(ObjectImpl.java:112)
- at org.omg.CosNaming.NamingContextHelper.narrow(NamingContextHelper.java
- :69)
- at com.sun.jndi.cosnaming.CNCtx.setOrbAndRootContext(CNCtx.java:345)
- at com.sun.jndi.cosnaming.CNCtx.initUsingCorbanameUrl(CNCtx.java:321)
- at com.sun.jndi.cosnaming.CNCtx.initUsingUrl(CNCtx.java:247)
- at com.sun.jndi.cosnaming.CNCtx.createUsingURL(CNCtx.java:85)
- at com.sun.jndi.url.iiop.iiopURLContextFactory.getUsingURLIgnoreRest(iio
- pURLContextFactory.java:56)
- at com.sun.jndi.url.iiop.iiopURLContext.getRootURLContext(iiopURLContext
- .java:44)
- at com.sun.jndi.toolkit.url.GenericURLContext.lookup(GenericURLContext.j
- ava:182)
- at javax.naming.InitialContext.lookup(InitialContext.java:351)
- at javax.management.remote.rmi.RMIConnector.findRMIServerJNDI(RMIConnect
- or.java:1817)
- at javax.management.remote.rmi.RMIConnector.findRMIServer(RMIConnector.j
- ava:1787)
- at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:25
- 9)
- at javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFacto
- ry.java:248)
- at sun.tools.jconsole.ProxyClient.<init>(ProxyClient.java:117)
- at sun.tools.jconsole.ProxyClient.getProxyClient(ProxyClient.java:87)
- at sun.tools.jconsole.JConsole$2.run(JConsole.java:410)
- Caused by: java.net.ConnectException: Connection refused: connect
- at sun.nio.ch.Net.connect(Native Method)
- at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:464)
- at java.nio.channels.SocketChannel.open(SocketChannel.java:146)
- at com.sun.corba.se.impl.transport.DefaultSocketFactoryImpl.createSocket
- (DefaultSocketFactoryImpl.java:60)
- at com.sun.corba.se.impl.transport.SocketOrChannelConnectionImpl.<init>(
- SocketOrChannelConnectionImpl.java:188)
- ... 23 more
经过一系列不堪回首的漫长过程,发现这个问题可能是jconsole的bug,而此bug已经在sun的bug Report中列出来了,而且,目前此bug的状态: State 11-Closed, Not a Defect, bug。关于此bug的具体信息请参考:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6209663
此时,使用linux的“hostname -i”命令查看,发现当前服务器的hostname为:127.0.0.1,使用“hostname newhosename”修改成实际的IP地址,仍然不能解决上述问题。
针对此bug,也有不少高手们提出了相应的解决方案,具体方案列表如下:(以下6条摘自:http://shallon.javaeye.com/blog/129750)
使用JCONSOLE监控远程LINUX运行的JAVA进程,总是在报连接失败的错误。
1)被监控的服务器端增加启动参数
-Dcom.sun.management.jmxremote.port=8999
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
2)本机上使用jconsole连接远程的8999端口
报连接失败,检查网络情况,8999端口有在监听等待,本地机器能够连接上对端机器的8999端口。切换了一台linux机器,情况依旧。
3)去网上找了一把,发现一个网友一年多前也在为此苦恼,所不同的是网友用的是JDK1.5,我用的是JDK 1.6。该网文链接如下:
http://svr.wjworld.net/soft/P1558/I7132389.shtml(发现已经不可用)
4)尝试抓包分析,发现是RMI的二进制协议,无法解读,报文中有127.0.0.1等字眼,从关键字判断是RMI下载的STUB文件。
5)继续查找,发现了一篇有价值的文章谈到这个问题,是服务器端解释机器名的问题,如果服务器端hostname -i被定向到127.0.0.1则会出现连接失败的问题。修改/etc/hosts文件,使hostname -i 指向正确的IP,JConsole终于可以正常连接。
这篇文章链接如下:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6209663
6)可能的问题原因分析:JCONSOLE连接上监控的进程,从监控进程下载了RMI远程调用的STUB文件?该STUB访问服务器的进程,
服务器端的地址可能是通过hostname -i类似机制获得。
综合上述方案,修改liunx下的hosts文件,相对简单,于是,修改/etc/hosts文件,将其第一行的“127.0.0.1 localhost.localdomain localhost”,修改为:“192.168.1.234 localhost.localdomain localhost”,其中,“192.168.1.234”为实际的服务器的IP地址。
重启linux,此时,在终端中输入“hosename -i”,结果为实际设置的IP地址,这里是192.168.1.234。再次使用jconsole连接此linux服务器,OK,一切正常,久违的JConsole图形界面显示出来。
另外,上述第一条中的“8999”为实际的需要监控的java服务的端口号。
但是,在实际情况下,第一条貌似不怎么管用,添加完第一条的参数后,应用服务器起不来了。
又找到另外一篇文章(出处:http://www.51testing.com/?uid-113838-action-viewspace-itemid-132703):
1、首先需要停止正在运行的服务:resin-XXX stop
2、然后在Linux的服务器启动项中添加如下信息:
-Djava.rmi.server.hostname=192.168.1.122
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=911
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
比如说我需要了解在压力测试过程中Linux系统中resin服务器的资源占用情况,那么我就可以在resin的启动项中加入上述信息,这样通过本机Windows中JDK的Jconsole来监控了。
其中第一个参数可以用来设置欲连接的Linux机器的IP地址,该项必须设置,否则远程连接会因为解析到127.0.0.1出现连接失败的情况。
如果不设置该项,也可以通过修改Linux的/etc/hosts文件,使hostname -i指向正确的IP,所以还是该选项更为方便。
第三个参数是设置欲连接到Linux机器上的端口号,在不跟Linux中现有端口冲突的情况下,可随意设置该端口
3、重新启动服务resin-XXX start
4、最后双击本机../jdk1.6/bin/jconsole.exe,启动Jconsole监控界面,在远程连接处输入:192.168.1.122:911,输入Linux主机的用户名和密码,连接即可,因为第2点中的第5项-Dcom.sun.management.jmxremote.authenticate=false,设置成了false,所以如果不知道Linux机器的用户名和密码,也可以不输入,直接连接
综上所述,该问题就解决啦,用户Jconsole来监控java服务器的资源占用情况,非常方便直观高效。