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

发布于 2024-10-30 02:14:10 字数 332 浏览 2 评论 0原文

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

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

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

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

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 recommend using JConsole! JConsole is not suitable because it is general JMX client and have negative effect on main program performance.

  • Samples on oracle site use RMIConnector and host:port params but I don't know:
    where should set jmx port?

  • JConsole have an option to connect to java processes by PID. But I don't find any method in JMX api that have PID as input param.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

奶茶白久 2024-11-06 02:14:10

我们使用类似以下内容以编程方式连接到我们的 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();
}

我们还有可以执行以下操作的代码:以编程方式将自身发布到虚拟机参数之外的特定端口,但这比您需要的更有趣,我认为。


据我所知,就“通过 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 服务器并将 beans 发布到远程客户端。

// 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)。

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

药祭#氼 2024-11-06 02:14:10

需要澄清的是,如果您只对获取本地 JMX 统计信息感兴趣,则无需使用远程 api。只需使用 java.lang.management.ManagementFactory 即可:

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

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

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();
...
甜点 2024-11-06 02:14:10
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;
}

这要求您在 JVM 启动时为您尝试读取的进程使用 jmxremote 参数。
无需在启动时传递 jmxremote 参数就能够做到这一点。您必须使用 Attach api(仅适用于使用 Java 6 及更高版本的程序。

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.

迎风吟唱 2024-11-06 02:14:10

最简单的意思是:

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

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) ...
}
装纯掩盖桑 2024-11-06 02:14:10

这是如何通过 Java 程序的 PID 获得 JMX 连接(仅适用于版本 <= Java 8):

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

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();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文