How to connect to mBeanServer in another local process?

If you set the system property "com.sun.management.jmxremote" when starting the JVM, you can start jconsole or visualvm and connect to this local mBeanServer. I want to do the same thing that they do, but cannot figure out how to do it.

Is there a service URL that can be used to identify a locally running JVM?

I know that I can do this by setting up the jmxmp or rmi listener on a specific port and then connecting to that port, but I do not want to do this because it means I need to manage the ports and know which port goes to which jvm (we run several jvms on the same server).

+3
source share
2 answers

Thanks to Nicholas and Scott for the post and discussion. I was able to bring this together based on this information and some trial and error.

Exchange so that others do not have to do the same work with their feet. This will connect to the JVM and use its memory.

import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;
import com.sun.tools.attach.spi.AttachProvider;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeData;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class AttachFun {

    public static void main(String[] args) throws Exception {
        final AttachProvider attachProvider = AttachProvider.providers().get(0);

        VirtualMachineDescriptor descriptor = null;
        for (VirtualMachineDescriptor virtualMachineDescriptor : attachProvider.listVirtualMachines()) {
            if (pickThisOne(virtualMachineDescriptor)) {
                descriptor = virtualMachineDescriptor;
                break;
            }
        }

        if (descriptor == null) throw new RuntimeException("You didn't pick one");

        final VirtualMachine virtualMachine = attachProvider.attachVirtualMachine(descriptor);
        virtualMachine.loadAgent("/System/Library/Frameworks/JavaVM.framework/Home/lib/management-agent.jar", "com.sun.management.jmxremote");
        final Object portObject = virtualMachine.getAgentProperties().get("com.sun.management.jmxremote.localConnectorAddress");

        final JMXServiceURL target = new JMXServiceURL(portObject + "");
        final JMXConnector connector = JMXConnectorFactory.connect(target);
        final MBeanServerConnection remote = connector.getMBeanServerConnection();

        final ObjectName memory = new ObjectName("java.lang:type=Memory");
        CompositeData cd = (CompositeData) remote.getAttribute(memory, "HeapMemoryUsage");

        final Long used = (Long) cd.get("used");
        System.out.println(used);

    }

    private static boolean pickThisOne(VirtualMachineDescriptor virtualMachineDescriptor) {
        // TODO
        return false;
    }
}
+7
source

You will need to Attach the API . It will find managed JVMs with API support, compatible with the API, on the same host and return metadata to each, and also enable the JMXConnector. This is basically what you see when you start JConsole, and the JVM is displayed on the connection menu, including Java 1.6+ instances that did not start using any special JMX command line directives.

// Nikolay

+1
source

Source: https://habr.com/ru/post/1782829/


All Articles