2012-12-18 82 views
1

我试图使用jconsole作为一个JMX客户端通过ssh连接到远程Java应用JConsole连接到远程JVM通过SSH

我已经建立了CustomAgent上https://blogs.oracle.com/jmxetc/entry/connecting_through_firewall_using_jmx

描述的代码代理在这里

/** 
* CustomAgent.java 

* https://blogs.oracle.com/jmxetc/entry/connecting_through_firewall_using_jmx 
*/ 

package example.rmi.agent; 

import java.io.IOException; 
import java.lang.management.ManagementFactory; 
import java.net.InetAddress; 
import java.rmi.registry.LocateRegistry; 
import java.util.HashMap; 
import javax.management.MBeanServer; 
import javax.management.remote.JMXConnectorServer; 
import javax.management.remote.JMXConnectorServerFactory; 
import javax.management.remote.JMXServiceURL; 

/** 
* This CustomAgent will start an RMI COnnector Server using only 
* port "example.rmi.agent.port". 
* 
* @author dfuchs 
*/ 
public class CustomAgent { 

    private CustomAgent() { } 

    public static void premain(String agentArgs) 
    throws IOException { 

     // Ensure cryptographically strong random number generator used 
     // to choose the object number - see java.rmi.server.ObjID 
     // 
     System.setProperty("java.rmi.server.randomIDs", "true"); 

     // Start an RMI registry on port specified by example.rmi.agent.port 
     // (default 3000). 
     // 
     final int port= Integer.parseInt(
       System.getProperty("example.rmi.agent.port","3000")); 
     System.out.println("Create RMI registry on port "+port); 
     LocateRegistry.createRegistry(port); 


     // Retrieve the PlatformMBeanServer. 
     // 
     System.out.println("Get the platform's MBean server"); 
     MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 

     // Environment map. 
     // 
     System.out.println("Initialize the environment map"); 
     HashMap<String,Object> env = new HashMap<String,Object>(); 

     // This where we would enable security - left out of this 
     // for the sake of the example.... 
     // 

     // Create an RMI connector server. 
     // 
     // As specified in the JMXServiceURL the RMIServer stub will be 
     // registered in the RMI registry running in the local host on 
     // port 3000 with the name "jmxrmi". This is the same name the 
     // out-of-the-box management agent uses to register the RMIServer 
     // stub too. 
     // 
     // The port specified in "service:jmx:rmi://"+hostname+":"+port 
     // is the second port, where RMI connection objects will be exported. 
     // Here we use the same port as that we choose for the RMI registry. 
     // The port for the RMI registry is specified in the second part 
     // of the URL, in "rmi://"+hostname+":"+port 
     // 
     System.out.println("Create an RMI connector server"); 
     final String hostname = InetAddress.getLocalHost().getHostName(); 
     //JMXServiceURL url = 
     // new JMXServiceURL("service:jmx:rmi://"+hostname+ 
     // ":"+port+"/jndi/rmi://"+hostname+":"+port+"/jmxrmi"); 

     //Added to allow connection through a firewall 
     // We use (port+1) to export the RMI connection objects 
     JMXServiceURL url = 
      new JMXServiceURL("service:jmx:rmi://"+hostname+ 
      ":"+(port+1)+"/jndi/rmi://"+hostname+":"+port+"/jmxrmi"); 




     // Now create the server from the JMXServiceURL 
     // 
     JMXConnectorServer cs = 
      JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs); 

     // Start the RMI connector server. 
     // 
     System.out.println("Start the RMI connector server on port "+port); 
     cs.start(); 
    } 
} 

构建脚本是在这里

<project name="Agent" basedir="." default="main"> 

    <property name="src.dir"  value="src"/> 
    <property name="build.dir" value="build"/> 
    <property name="classes.dir" value="${build.dir}/classes"/> 
    <property name="jar.dir"  value="${build.dir}/jar"/> 
    <property name="main-class" value="example.rmi.agent.CustomAgent"/> 

    <target name="clean"> 
     <delete dir="${build.dir}"/> 
    </target> 

    <target name="compile"> 
     <mkdir dir="${classes.dir}"/> 
     <javac srcdir="${src.dir}" destdir="${classes.dir}"/> 
    </target> 

    <target name="jar" depends="compile"> 
     <mkdir dir="${jar.dir}"/> 
     <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}"> 
      <manifest> 
       <attribute name="Main-Class" value="${main-class}"/> 
      </manifest> 
     </jar> 
    </target>  

    <target name="run" depends="jar"> 
     <java jar="${jar.dir}/${ant.project.name}.jar" fork="true"/> 
    </target>  
    <target name="clean-build" depends="clean,jar"/>  
    <target name="main" depends="clean,run"/> 

    <!-- Builds dist.agent.jar -->  
    <target name="build-agent-jar" description="build an agent jar that can be used with -javaagent" depends="compile"> 
     <mkdir dir="${jar.dir}"/> 
     <jar basedir="${classes.dir}" destfile="${jar.dir}/${ant.project.name}.jar"> 
       <manifest> 
        <attribute name="Premain-Class" value="example.rmi.agent.CustomAgent"/> 
       </manifest> 
     </jar> 
     <echo>To use this application with agent try:</echo> 
     <echo>java -Dexample.rmi.port=3000 -javaagent:${dist.agent.jar} -classpath [application-classpath] [application-classpath] [application-main-class]</echo> 
    </target> 
</project> 

开始使用在远程机器上的应用程序

的java -javaagent:试剂/建造/罐/ agent.jar中 -Dexample.rmi.agent.port = 6004 -server -server -Dcom.sun.management .jmxremote.authenticate =“false”-Dcom.sun.management.jmxremote =“true”-Dcom.sun.management.jmxremote.ssl =“false”-Dcom.sun.management.jmxremote.local.only =“false” -jar路径到我的应用程序内/ app.jar

两个端口的主机,6004和6005,我可以通过JConsole的连接应用程序。如果JConsole的是本地的应用程序开放。

我再创建2条SSH隧道

SSH隧道SSH-L 6004:本地主机:6004 FOO @服务器SSH隧道 的ssh -L 6005:本地主机:6005 FOO @服务器

的隧道已成功创建。我可以在这些端口上远程登录。

现在的问题是,我不能使用JConsole虽然

服务远程连接:JMX:RMI://本地主机:6005/JNDI/RMI://本地主机:6004/jmxrmi

JConsole的-J-Djava.util.logging.config.file = logging.properties -debug

JConsole的是由启动

错误日志:

Dec 18, 2011 4:57:46 PM RMIConnector connect 
FINER: [javax.management.remote.rmi.RMIConnector: jmxServiceURL=service:jmx:rmi://localhost:6005/jndi/rmi://localhost:6004/jmxrmi] 

连接... 2011年12月18日下午4时57分46秒RMIConnector连接 FINER:[javax.management.remote.rmi.RMIConnector:JMXServiceURL中=服务:jmx:rmi:// localhost:6005/jndi/rmi:// localhost:6004/jmxrmi] 找到存根... 2011年12月18日下午4时58分49秒RMIConnector连接 FINER:[javax.management .remote.rmi.RMIConnector:jmxServiceURL = service:jmx:rmi:// localhost:6005/jndi/rmi:// localhost:6004/jmxrmi] 连接存根... D ec 18,2011 4:58:49 PM RMIConnector connect FINER:[javax.management.remote.rmi.RMIConnector:jmxServiceURL = service:jmx:rmi:// localhost:6005/jndi/rmi:// localhost:6004/jmxrmi] 正在建立连接... 2011年12月18日下午4:59:52 RMIConnector connect FINER:[javax.management.remote.rmi.RMIConnector:jmxServiceURL = service:jmx:rmi:// localhost:6005/jndi/rmi:// localhost:6004/jmxrmi] 未能连接:java.rmi.ConnectException:连接拒绝到 主机:172.16.0.111;嵌套异常是: java.net.ConnectException:连接超时 java.rmi.ConnectException:连接拒绝主机:172.16.0.111;嵌套异常是: java.net.ConnectException:连接超时 at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619) at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel。 java:216) at Sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202) at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:128) at javax.management.remote。 rmi.RMIServerImpl_Stub.newClient(未知 源) 在javax.management.remote.rmi.RMIConnector.getConnection(RMIConnector.java:2343) 在javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:296) at javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:267) at sunx.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:226) at sun.tools.jconsole.ProxyClient.tryConnect(ProxyClient.java:366) at sun.tools.jconsole.ProxyClient.connect(ProxyClient。 java:316) at sun.tools.jconsole.VMPanel $ 2.run(VMPanel.java:298) 引起:java.net.ConnectException:连接超时 at java.net.PlainSocketImpl.socketConnect(Native Method) 在java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:327) 在java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:193) 在java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:180) 在java的.net.SocksSocketImpl.connec t(SocksSocketImpl.java:384) at java.net.Socket.connect(Socket.java:546) at java.net.Socket.connect(Socket.java:495) at java.net.Socket。(Socket .java:392) at java.net.Socket。(Socket.java:206) at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40) at sun.rmi.transport.proxy。 RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:146) 在sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613) ...... 11多个

回答

2

我需要添加

-Djava.rmi.server.hostname =本地主机

到-server参数现在热点7 JVM直接支持

+0

是的,万一你有多个网络适配器。您需要使用上述属性指定要侦听远程连接的适配器的IP地址。 –

0

尝试运行您的服务器有以下选项:

-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=6004 
-Dcom.sun.management.jmxremote.rmi.port=6004 
-Dcom.sun.management.jmxremote.ssl=false 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.local.only=true 

一旦你有一个6004的隧道试试这个与jcon鞋底:

jconsole -J-DsocksProxyHost=127.0.0.1 -J-DsocksProxyPort=6004 service:jmx:rmi:///jndi/rmi://0.0.0.0:6004/jmxrmi -J-DsocksNonProxyHosts=