javalocalhostrmijmxjconsole

How to connect to a java program on localhost jvm using JMX?


I should connect to a java program on localhost jvm using JMX. In other words I want to develop a JMX client to config a java program on localhost.


Solution

  • We use something like the following to programatically connect to our JMX servers. You should run your server with something like the following arguments:

    -Dcom.sun.management.jmxremote
    -Dcom.sun.management.jmxremote.authenticate=false
    -Dcom.sun.management.jmxremote.port=1234
    -Dcom.sun.management.jmxremote.ssl=false
    

    To bind to a particular address you'll need to add the following VM arguments:

    -Djava.rmi.server.hostname=A.B.C.D
    

    Then you can connect to your server using JMX client code like the following:

    String host = "localhost";  // or some A.B.C.D
    int port = 1234;
    String url = "service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/jmxrmi";
    JMXServiceURL serviceUrl = new JMXServiceURL(url);
    JMXConnector jmxConnector = JMXConnectorFactory.connect(serviceUrl, null);
    try {
       MBeanServerConnection mbeanConn = jmxConnector.getMBeanServerConnection();
       // now query to get the beans or whatever
       Set<ObjectName> beanSet = mbeanConn.queryNames(null, null);
       ...
    } finally {
       jmxConnector.close();
    }
    

    We also have code that can programatically publish itself to a particular port outside of the VM arguments but that's more fu than you need I think.


    In terms of connecting "by pid", you need to be using Java6 to do it from Java land as far as I know. I've not used the following code but it seems to work.

    List<VirtualMachineDescriptor> vms = VirtualMachine.list();
    for (VirtualMachineDescriptor desc : vms) {
        VirtualMachine vm;
        try {
            vm = VirtualMachine.attach(desc);
        } catch (AttachNotSupportedException e) {
            continue;
        }
        Properties props = vm.getAgentProperties();
        String connectorAddress =
            props.getProperty("com.sun.management.jmxremote.localConnectorAddress");
        if (connectorAddress == null) {
            continue;
        }
        JMXServiceURL url = new JMXServiceURL(connectorAddress);
        JMXConnector connector = JMXConnectorFactory.connect(url);
        try {
            MBeanServerConnection mbeanConn = connector.getMBeanServerConnection();
            Set<ObjectName> beanSet = mbeanConn.queryNames(null, null);
            ...
        } finally {
            jmxConnector.close();
        }
    }
    

    I've also the author of SimpleJMX package which makes it easy to start a JMX server and publish beans to remote clients.

    // create a new server listening on port 8000
    JmxServer jmxServer = new JmxServer(8000);
    // start our server
    jmxServer.start();
    // register our lookupCache object defined below
    jmxServer.register(lookupCache);
    jmxServer.register(someOtherObject);
    // stop our server
    jmxServer.stop();
    

    It does have a client interface as well but right now it doesn't have any mechanisms to find processes by PID -- only host/port combinations are supported (in 6/2012).