Java 如何在另一个本地进程中连接到mBeanServer?

Java 如何在另一个本地进程中连接到mBeanServer?,java,jmx,jconsole,visualvm,Java,Jmx,Jconsole,Visualvm,如果在启动JVM时设置“com.sun.management.jmxremote”系统属性,则可以运行jconsole或visualvm并连接到该本地mBeanServer。我想做和他们一样的事情,但不知道怎么做 是否有一个服务URL可用于标识本地运行的JVM 我知道我可以通过在特定端口上设置jmxmp或rmi侦听器,然后连接到该端口来实现这一点,但我不想这样做,因为这意味着我必须管理端口并知道哪个端口连接到哪个jvm(我们在同一台服务器上运行多个jvm)。您需要。它将在同一台主机上找到正在运行

如果在启动JVM时设置“com.sun.management.jmxremote”系统属性,则可以运行jconsole或visualvm并连接到该本地mBeanServer。我想做和他们一样的事情,但不知道怎么做

是否有一个服务URL可用于标识本地运行的JVM

我知道我可以通过在特定端口上设置jmxmp或rmi侦听器,然后连接到该端口来实现这一点,但我不想这样做,因为这意味着我必须管理端口并知道哪个端口连接到哪个jvm(我们在同一台服务器上运行多个jvm)。

您需要。它将在同一台主机上找到正在运行的[Attach API capable]JVM,并在每个JVM上返回元数据,同时启用JMXConnector。这基本上是启动JConsole时看到的,连接菜单显示正在运行的JVM,包括未使用任何特殊JMX命令行指令启动的Java 1.6+实例


//尼古拉斯

感谢尼古拉斯和斯科特的帖子和讨论。基于这些信息和一些尝试和错误,我们能够将这些信息拼凑在一起

分享,这样其他人就不必做同样的腿部工作。这将连接到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;
    }
}

attach API为我获得了JVM的句柄,但没有获得该JVM中mBeanServer的句柄。attachapi的javadoc展示了一个使用它远程加载代理的例子:Right。如果加载JRE的内置管理代理(/JRE/lib/management agent.jar)并指定侦听端口(例如vm.loadAgent(agent,“com.sun.management.jmxremote.port=5000”);则可以使用JMX远程API连接端口5000上的MBeanServer。如果您正在寻找一种在JVM中访问MBeanServer而无需端口访问的方法。。。。。。我不确定。。。。你也许可以开发一个基于FIFO的协议或其他什么。我不想在没有端口访问的情况下连接。。。我只是不想指定要使用哪个端口。事实证明,如果您没有指定端口(即调用vm.loadAgent(agent,“com.sun.management.jmxremote”)),那么jvm会选择一个随机高端口。然后,我可以调用vm.getAgentProperties().get(“com.sun.management.jmxremote.localConnectorAddress”)来获取连接到mBeanServer的URL。谢谢尼古拉斯的帮助!Scott Greenman familysearch.orgNice示例,您也可以从这里找到类似的详细示例:使用JDK 8,现在连接加载代理并获取本地地址要简单得多。您应该使用
virtualMachine.startOcalManagementAgent
方法。