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

后端 未结 5 1622
孤独总比滥情好
孤独总比滥情好 2020-12-04 08:23

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.

  • Don\'t r

相关标签:
5条回答
  • 2020-12-04 09:01
    List<VirtualMachineDescriptor> vm = new ArrayList<VirtualMachineDescriptor>();
            jvmList = new JVMListManager();
    
            vm = jvmList.listActiveVM();
    
            for (VirtualMachineDescriptor vmD : vm) 
            {
                try
                {
    
                //importFrom is taking a process ID and returning a service url in a String Format
                String ServiceUrl = ConnectorAddressLink.importFrom(Integer.parseInt(vmD.id().trim()));
                JMXServiceURL jmxServiceUrl = new JMXServiceURL(ServiceUrl);
    
                jmxConnector = JMXConnectorFactory.connect(jmxServiceUrl, null);
                con = jmxConnector.getMBeanServerConnection();
                CompilationMXBean compMXBean = ManagementFactory.newPlatformMXBeanProxy(con
                       , ManagementFactory.COMPILATION_MXBEAN_NAME
                       , CompilationMXBean.class);
                }catch(Exception e)
                {
                //Do Something  
                }
            }
    
    
    protected List listActiveVM() {
        List<VirtualMachineDescriptor> vm = VirtualMachine.list();
    
        return vm;
    }
    

    This requires you to use the jmxremote argument at JVM startup for the process you are trying to read. TO be able to do it without having to pass a jmxremote argument at startup. You will have to use the attach api(only applicable for Programs using Java 6 and higher.

    0 讨论(0)
  • 2020-12-04 09:06

    To clarify, if you are only interested in getting local JMX stats, you don't need to use the remote api. Just use java.lang.management.ManagementFactory:

    MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
    memoryMXBean.getHeapMemoryUsage().getMax();
    ...
    
    List<MemoryPoolMXBean> beans = ManagementFactory.getMemoryPoolMXBeans();
    ...
    
    0 讨论(0)
  • 2020-12-04 09:06

    Simplest means:

    import javax.management.Attribute;
    import javax.management.AttributeList;
    import java.lang.management.ManagementFactory;
    import javax.management.MBeanServer;
    import javax.management.ObjectName;
    
    // set a self JMX connection
    MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
    // set the object name(s) you are willing to query, here a CAMEL JMX object
    ObjectName objn = new ObjectName("org.apache.camel:context=*,type=routes,name=\"route*\"");
    Set<ObjectName> objectInstanceNames = mBeanServer.queryNames(objn, null);
    for (ObjectName on : objectInstanceNames) {
        // query a number of attributes at once
        AttributeList attrs = mBeanServer.getAttributes(on, new String[] {"ExchangesCompleted","ExchangesFailed"});
        // process attribute values (beware of nulls...)
        // ... attrs.get(0) ... attrs.get(1) ...
    }
    
    0 讨论(0)
  • 2020-12-04 09:15

    This is how you can get a JMX connection to a Java Program with it's PID (for version <= Java 8 only) :

    import sun.management.ConnectorAddressLink;
    import javax.management.*;
    
    public static MBeanServerConnection getLocalJavaProcessMBeanServer(int javaProcessPID) throws IOException {
        String address = ConnectorAddressLink.importFrom(javaProcessPID);
        JMXServiceURL jmxUrl = new JMXServiceURL(address);
        return JMXConnectorFactory.connect(jmxUrl).getMBeanServerConnection();
    }
    
    0 讨论(0)
  • 2020-12-04 09:20

    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).

    0 讨论(0)
提交回复
热议问题