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

时间:2011-04-05 13:52:42

标签: java localhost rmi jmx jconsole

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

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

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

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

5 个答案:

答案 0 :(得分:63)

我们使用类似以下内容以编程方式连接到我们的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参数之外的特定端口,但这比我想象的要多得多。


就连接“by 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 package的作者,它可以轻松启动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查找进程的机制 - 仅支持主机/端口组合(2012年6月)。

答案 1 :(得分:4)

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

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

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

答案 2 :(得分:3)

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及更高版本的程序。

答案 3 :(得分:1)

最简单意味着:

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

答案 4 :(得分:0)

这是如何使用其PID(仅对于版本<= Java 8)获得与Java程序的JMX连接:

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