如何用JMX連線本地JVM上執行的Java程式

ImportNew發表於2015-05-20

問題:

我需要使用JMX連線本地JVM的Java程式。換句話說,我想開發一個JMX的客戶端來配置一個本地Java程式。

  • 請不要推薦使用JConsole!JConsole不合適,因為JConsole是一個通用的JMX客戶端,對主程式的效能存在負面影響。
  • Oracle網站上有一個使用RMIConnector和“主機 : 埠號”為引數的例子,但是我不知道在什麼地方設定JMX的埠號?
  • JConsole可以選擇PID來連線Java程式。但是在JMX的API中,我找不到任何方法是使用PID作為引數的。

回覆:

我們使用一些類似下面的程式來連線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來連線,據我現在所知,你需要使用Java 6以上的版本。我沒使用過下面的程式碼,但是看起是可以正常工作的:

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。

//建立一個新的伺服器並監聽8000埠
JmxServer jmxServer = new JmxServer(8000);
//啟動伺服器
jmxServer.start();
//註冊下面定義的lookupCache物件
jmxServer.register(lookupCache);
jmxServer.register(someOtherObject);
//停止服務
jmxServer.stop();

該包確實有一個客戶端的介面,但是當前沒有人一種機制是可以通過PID來查詢程式的,只支援主機/埠的組合方式查詢。

相關文章