如何使用JMX连接到localhost jvm上的Java程序?

2022-09-01 00:59:07

我应该使用JMX连接到localhost jvm上的Java程序。换句话说,我想开发一个JMX客户端来配置localhost上的java程序。

  • 不建议使用JConsole!JConsole不适合,因为它是通用的JMX客户端,并且对主程序性能有负面影响。

  • oracle站点上的示例使用RMIConnector和host:port参数,但我不知道:应该在哪里设置jmx端口?

  • JConsole可以选择通过PID连接到java进程。但是我在JMX api中找不到任何将PID作为输入参数的方法。


答案 1

我们使用类似下面的内容以编程方式连接到我们的 JMX 服务器。您应该使用以下参数运行服务器:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.port=1234
-Dcom.sun.management.jmxremote.ssl=false

若要绑定到特定地址,需要添加以下 VM 参数:

-Djava.rmi.server.hostname=A.B.C.D

然后,您可以使用 JMX 客户机代码连接到服务器,如下所示:

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();
}

我们也有代码可以编程地将自身发布到VM参数之外的特定端口,但这比你想象的要多。


就“通过pid”连接而言,据我所知,您需要使用Java6从Java土地上做到这一点。我没有使用以下代码,但它似乎有效。

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();
    }
}

我还是SimpleJMX软件包的作者,它使启动JMX服务器并将Bean发布到远程客户端变得容易。

// 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();

它确实也有一个客户端接口,但现在它没有任何机制来通过PID查找进程 - 仅支持主机/端口组合(在6/2012中)。


答案 2

为了澄清,如果您只对获取本地JMX统计信息感兴趣,则不需要使用远程API。只需使用 :java.lang.management.ManagementFactory

MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
memoryMXBean.getHeapMemoryUsage().getMax();
...

List<MemoryPoolMXBean> beans = ManagementFactory.getMemoryPoolMXBeans();
...

推荐