2011-04-05 88 views
35

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

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

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

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

+1

两个主程序和JMX客户端是独立程序(Java SE)。 – mjafari 2011-04-05 14:02:07

+0

另请参阅http://www.pongasoft.com/blog/yan/entry/connecting_to_a_local_vm/ – 2012-03-07 18:27:40

回答

56

我们使用类似下面的内容以编程方式连接到我们的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来完成它。我没有使用下面的代码,但它似乎工作。

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服务器并发布豆到远程客户端。

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

+1

谢谢格雷!你(或其他人)可以回答我的第二个问题(使用PID的本地jmx连接)吗? – mjafari 2011-04-09 08:56:58

+0

如果由于某种原因,ConnectorAddress为空,您可以尝试以媒体方式加载代理。请参阅http://www.pongasoft.com/blog/yan/entry/connecting_to_a_local_vm/ – 2014-12-12 14:00:11

+0

您有一行编译问题:jmxConnector.close(); – shlomi33 2017-01-16 07:53:02

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

这需要您使用jmxremote参数在JVM启动要尝试读取进程。 能够在启动时无需传递jmxremote参数即可完成此操作。为了说明一下,如果您只想获取本地JMX统计信息,则不需要使用远程API,只需要使用附加API(仅适用于使用Java 6和更高版本的程序)

4

java.lang.management.ManagementFactory

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

List<MemoryPoolMXBean> beans = ManagementFactory.getMemoryPoolMXBeans(); 
... 
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) ... 
} 
相关问题