我正在尝试通过ssh使用jconsole作为JMX客户端连接到远程Java应用程序
我已经构建了https://blogs.oracle.com/jmxetc/entry/connecting_through_firewall_using_jmx上描述的CustomAgent
代理的代码在这里
/**
* 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:agents / build / jar / Agent.jar
-Dexample.rmi.agent.port = 6004-服务器-服务器-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:localhost:6004 foo @ server ssh隧道
ssh -L 6005:localhost:6005 foo @ server
隧道创建成功。我可以在这些端口上远程登录。
现在的问题是尽管我无法使用Jconsole进行远程连接
服务:jmx:rmi:// localhost:6005 / jndi / rmi:// localhost:6004 / jmxrmi
jconsole由以下人员启动:
jconsole -J-Djava.util.logging.config.file = logging.properties-调试
错误日志是:
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 connect
罚款:[javax.management.remote.rmi.RMIConnector:jmxServiceURL = service:jmx:rmi:// localhost:6005 / jndi / rmi:// localhost:6004 / jmxrmi]
寻找存根...
2011年12月18日,下午4:58:49 RMIConnector connect
罚款:[javax.management.remote.rmi.RMIConnector:jmxServiceURL = service:jmx:rmi:// localhost:6005 / jndi / rmi:// localhost:6004 / jmxrmi]
连接存根...
2011年12月18日,下午4:58:49 RMIConnector connect
罚款:[javax.management.remote.rmi.RMIConnector:jmxServiceURL = service:jmx:rmi:// localhost:6005 / jndi / rmi:// localhost:6004 / jmxrmi]
正在建立连接...
2011年12月18日下午4:59:52 RMIConnector connect
罚款:[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:连接超时
在sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619)
在sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216)
在sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
在sun.rmi.server.UnicastRef.invoke(UnicastRef.java:128)
在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)
在javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:267)
在javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:226)
在sun.tools.jconsole.ProxyClient.tryConnect(ProxyClient.java:366)
在sun.tools.jconsole.ProxyClient.connect(ProxyClient.java:316)
在sun.tools.jconsole.VMPanel $ 2.run(VMPanel.java:298)
原因:java.net.ConnectException:连接超时
在java.net.PlainSocketImpl.socketConnect(本地方法)
在java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:327)
在java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:193)
在java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:180)
在java.net.SocksSocketImpl.connect(SocksSocketImpl.java:384)
在java.net.Socket.connect(Socket.java:546)
在java.net.Socket.connect(Socket.java:495)
在java.net.Socket。(Socket.java:392)
在java.net.Socket。(Socket.java:206)
在sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)
在sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:146)
在sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
...另外11个
最佳答案
我需要添加
-Djava.rmi.server.hostname =本地主机
到java -server参数
关于java - 通过SSH将Jconsole连接到远程JVM,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13937965/