我有一个程序,用于监视来自JMX远程代理的流程性能数据。

这些远程代理中的某些已配置为使用SSL,并将JVM参数com.sun.management.jmxremote.sslcom.sun.management.jmxremote.registry.ssl设置为true。其他的不受SSL保护,请将这些JVM参数设置为false。

我使用JMXConnector通过以下方法连接到这些远程代理:

private JMXConnector setUpConnection(String server, int jmxPort) {

    try {

        Registry r = LocateRegistry.getRegistry(server, jmxPort);

        HashMap<String, Object> env = new HashMap<String, Object>();

        String[] credentials = {"username", "password"};
        env.put(JMXConnector.CREDENTIALS, credentials);
        env.put("com.sun.jndi.rmi.factory.socket", new SslRMIClientSocketFactory());  // uncomment if needed


                JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + server + ":" + jmxPort + "/jmxrmi");
        return JMXConnectorFactory.newJMXConnector(url, env);

    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;

}


这种方法能够连接到我的SSL安全的远程代理,但不能连接到不使用SSL的远程代理。对于后一种情况,我收到的错误消息是:

java.io.IOException: Failed to retrieve RMIServer stub: javax.naming.CommunicationException [Root exception is java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is:
    javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake]


如果我删除以下行:

env.put("com.sun.jndi.rmi.factory.socket", new SslRMIClientSocketFactory());


然后发生了相反的情况,我现在可以连接到未配置为使用SSL的远程代理,但无法连接到SSL远程代理。在这种情况下,我获得的针对SSL配置的远程代理的错误消息是:

java.io.IOException: Failed to retrieve RMIServer stub: javax.naming.CommunicationException [Root exception is java.rmi.ConnectIOException: non-JRMP server at remote endpoint]


如果我没有将JVM参数com.sun.management.jmxremote.registry.ssl设置为true,那么我可以在忽略时连接到所有远程代理:

env.put("com.sun.jndi.rmi.factory.socket", new SslRMIClientSocketFactory());


但是,不能将此属性设置为false。

我想不惜一切代价避免使用两种不同的连接环境,一种用于SSL远程代理,另一种用于非SSL远程代理。我也无法将所有远程代理迁移到配置SSL。

最佳答案

我们的项目之一是使用以下代码片段获取JMXConnection。

private String provider = "";
private String jvmPort = "";
private JMXServiceURL jmxService = null;
private JMXConnector jmxConnector = null;
private RMIConnector rmiConnector = null;
private MBeanServerConnection beanServerConn = null;
.........

public boolean connectToJVM(String jvmURL, String user, String pass)
{
    boolean flag = false;
    beanServerConn = null ;
    try
    {
        jmxService = new JMXServiceURL(jvmURL);
        Map environment = new HashMap();
        int jmxconnect_timeout = 30000;
        environment.put("jmx.remote.protocol.provider.pkgs",provider);
        if (jmxconnect_timeout > 0) {
            environment.put("jmx.remote.x.request.waiting.timeout", Long.toString(jmxconnect_timeout));
        }
        boolean registrySSL = false;

        if(user.equalsIgnoreCase("none")|| (pass.equalsIgnoreCase("none")))
        {
            try
            {
                jmxConnector = JMXConnectorFactory.connect(jmxService,environment);
            }
            catch(IOException ioe)
            {
                registrySSL = true;
            }
        }
        else
        {
            String [] credentials={user,pass};
            environment.put(JMXConnector.CREDENTIALS, credentials);
            try
            {
                jmxConnector = JMXConnectorFactory.connect(jmxService,environment);
            }
            catch(IOException ioe)
            {
                registrySSL = true;
            }
        }

        if(registrySSL)
        {
            /*
                This if block runs when the "management.properties" file contains
                com.sun.management.jmxremote.registry.ssl=true

                This block of code is applicable both JDK5.0 & 6.0

                Only for JDK6.0
                ===============
                    environment.put("com.sun.jndi.rmi.factory.socket", new SslRMIClientSocketFactory());
                    beanServerConn = jmxConnector.getMBeanServerConnection();
            */

            try {
                MySslRMIClientSocketFactory csf = new MySslRMIClientSocketFactory(targetHost, Integer.parseInt(jvmPort), (int)jmxconnect_timeout);
                Registry registry = LocateRegistry.getRegistry(targetHost, Integer.parseInt(jvmPort), csf);
                RMIServer stub = (RMIServer) registry.lookup(jndiName);
                rmiConnector = new RMIConnector(stub, environment);
                rmiConnector.connect(environment);
                beanServerConn = rmiConnector.getMBeanServerConnection();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        else{
            beanServerConn = jmxConnector.getMBeanServerConnection();
        }

        if(beanServerConn == null)
        {
            System.out.println("Connection to JVM is not established for url : " + url);
            return false;
        }
        else
        {
            flag = true;
        }
    }
    catch(Exception ex)
    {
        System.out.println("Connection to JVM is not established for url : " + url);
        //ex.printStackTrace();
        return false;
    }
    return flag;
}

10-07 19:29
查看更多