artaxerxe
artaxerxe

Reputation: 6411

Getting remote JVM properties using JMX

Can anybody give me some guides on how to get the properties of a JVM after I created a JMX connection to it? I need to get those information programmatically. I searched for this without getting any hint. Any thoughts would be appreciated.

Upvotes: 2

Views: 4061

Answers (4)

Kris
Kris

Reputation: 3957

None of the answers already provided really worked for me. Some problems I had with them:

  • The accepted answer is little more than a pointer to the docs, not wrong, but no real help in working out all the details.
  • TabularDataSupport is a bit of PITA to unpack if you just want to get a Map of System properties. (The keys will be wrapped in lists and have to be unpacked; and the 'values' of the TabularDataSupport Map are not actually the values you want... but also still packed in a 'CompositeDataSupport' object which also has to be further unpacked.).
  • Using the JMX.newMXBeanProxy looked promising to avoid all this unpacking. But although it compiles... at runtime, I found the result from the proxy's getSystemProperties isn't actually correctly unpacked at all. It is still a TabularDataSupport object (yes, even though it's compile-time type says it should be a Map<String,String>, in reality it is not).

So here is something that actually does work for me with all these pitfalls worked out so that it gives the system properties as just a Map<String,String> just like you'd probably want.

package example;

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.Map;
import java.util.Map.Entry;

import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class GetJmxSystemProps {

    public static void main(String[] args) throws Exception {
        JMXServiceURL serviceUrl =  new JMXServiceURL("service:jmx:rmi://localhost:9111/jndi/rmi://localhost:9111/jmxrmi");
        JMXConnector jmxConnector = JMXConnectorFactory.connect(serviceUrl, null);
        MBeanServerConnection connection = jmxConnector.getMBeanServerConnection();
        RuntimeMXBean proxy = ManagementFactory.getPlatformMXBean(connection, RuntimeMXBean.class);
        Map<String, String> sysprops = proxy.getSystemProperties();
        for (Entry<String, String> e : sysprops.entrySet()) {
            System.out.println(e.getKey()+"="+e.getValue());
        }
    }
}

To summarize: The key point here is that using JMX.newMXBeanProxy to obtain a bean of type RuntimeMXBean is buggered and does not unpack the TabularDataSupport object into a Map<String,String> correctly. This problem is avoided by using method ManagementFactory.getPlatformMXBean instead.

Upvotes: 0

artaxerxe
artaxerxe

Reputation: 6411

As a hint: after you connect to JMX, seems to me that there's a standard MXBean interface, that implements java.lang.management.RuntimeMXBean. Related ObjectName should be:

ObjectName objName = new ObjectName("java.lang:type=Runtime");

and getting the proxy instance object is like that:

RuntimeMXBean runtimeMXBean = JMX.newMXBeanProxy(mbeanServer, objName, RuntimeMXBean.class, true);

Maybe this will help somebody else.

N.B. If somebody can provide link to documentation that specifies the need of RuntimeMXBean interface for JMX capable systems, that would be welcome.

Upvotes: 0

smicyk
smicyk

Reputation: 107

I think the smallest example should look like:

public class JMXSystemProperties {

public static void main(String[] args) throws Exception {
    JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9004/jmxrmi");
    JMXConnector jmxc = JMXConnectorFactory.connect(url, null);

    MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
    TabularDataSupport data = (TabularDataSupport) mbsc.getAttribute(new ObjectName("java.lang:type=Runtime"), "SystemProperties");
    for (Entry<Object, Object> entry : data.entrySet()) {
        CompositeDataSupport value = (CompositeDataSupport) entry.getValue();
        System.out.println(entry.getKey() + " = " + value.values());
    }
}
}

You can still use jvisualvm to see if all data are correct.

You can replace localhost and port 9004 in url to server and port which is better for you.

Thanks

Upvotes: 0

apangin
apangin

Reputation: 98294

Have a look at JMX tutorial and examples.

The properties you want can be obtained from RuntimeMXBean.

Upvotes: 2

Related Questions