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

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

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

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

  • JConsole可以通过PID连接到java进程。 但是我没有find任何有PID作为input参数的JMX API中的方法。

我们使用类似下面的内容以编程方式连接到我们的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=ABCD 

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

 String host = "localhost"; // or some ABCD 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服务器并将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月)。

为了说明一下,如果您只想获取本地JMX统计信息,则不需要使用远程API。 只要使用java.lang.management.ManagementFactory

 MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); memoryMXBean.getHeapMemoryUsage().getMax(); ... List<MemoryPoolMXBean> beans = ManagementFactory.getMemoryPoolMXBeans(); ... 
 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参数。 您将不得不使用附加API(仅适用于使用Java 6和更高版本的程序。

最简单的方法:

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