Как подключиться к mBeanServer в другом локальном процессе? - PullRequest
4 голосов
/ 30 декабря 2010

Если вы установили системное свойство com.sun.management.jmxremote при запуске JVM, вы можете запустить jconsole или visualvm и подключиться к этому локальному mBeanServer. Я хочу сделать то же самое, что они делают, но не могу понять, как.

Есть ли URL-адрес службы, который можно использовать для идентификации локально работающей JVM?

Я знаю, что мог бы сделать это, настроив прослушиватель jmxmp или rmi на определенный порт и затем подключившись к этому порту, но я не хочу этого делать, потому что это означает, что мне нужно управлять портами и знать, какой порт идет к какой jvm (мы запускаем несколько jvms на одном сервере).

Ответы [ 2 ]

7 голосов
/ 29 октября 2012

Спасибо Николасу и Скотту за пост и обсуждение. Был в состоянии собрать это воедино на основе этой информации и некоторых проб и ошибок.

Обмен, чтобы другим не приходилось выполнять одинаковую работу ногами. Это подключится к JVM и получит использование памяти.

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;
    }
}
1 голос
/ 31 декабря 2010

Вам необходим Attach API . Он найдет работающие JVM [с поддержкой API] на том же хосте и вернет метаданные для каждого, а также включит JMXConnector. Это в основном то, что вы видите, когда запускаете JConsole, и в меню подключения отображаются запущенные JVM, включая экземпляры Java 1.6+, которые не были запущены с какими-либо специальными директивами командной строки JMX.

// Николай

...