http://blog.csdn.net/derekjiang/article/details/4531952
最近在項目中用到了JMX,以前只是簡略的知道JMX是干什么的,卻沒有深入了解過,當然也沒有寫過相關的代碼,借著這個機會,正好學習一下。Google了n多大俠的相關帖子,對JMX有了一個初步的理解,這里總結出來,希望對大家有用。
?
關于什么是JMX,這里引用了網上找來的一個介紹:JMX(Java Management Extensions)是一個為應用程序植入管理功能的框架。JMX是一套標準的代理和服務,實際上,用戶可以在任何Java應用程序中使用這些代理和服務實現管理
?
老實說,看了這個介紹,我還是不太明白,用我們都能理解的大白話來說,JMX是一個框架,它提供了這樣一種功能:通過使用JMX,我們可以實時查詢應用程序中通過JMX向外公布的相應參數或者是其他應用數據,同時,我們也可以通過JMX來實時的調用應用程序使用JMX向外公布的接口,從而來實現一些操作。
?
準備工作
JMX是一份規范,SUN依據這個規范在JDK(1.3、1.4、5.0)提供了JMX接口。而根據這個接口的實現則有很多種,比如Weblogic的JMX實現、MX4J、JBoss的JMX實現。在SUN自己也實現了一份,不過在JDK1.4之前,這件JMX實現(一些JAR包)是可選的,你得去它的網站上下載。JDK5.0則內嵌了進來,安裝JDK5.0就可以開發基于JMX的代碼了。
但JDK5.0并非包含所有SUN的關于JMX的代碼,有一些工具類是排除在JDK5.0之外的。下面根據所使用的JDK版本情況,談一談開發環境的準備。 1、JDK1.3、1.4 去SUN網站下載SUN的JMX實現,共兩個ZIP文件,下載網址:http://java.sun.com/products/JavaManagement/download.html。 (1)jmx-1_2_1-ri.zip 解壓后的lib目錄包含:jmxri.jar、jmxtools.jar (2)jmx_remote-1_0_1_03-ri.zip 解壓后的lib目錄包含:jmxremote.jar、jmxremote_optional.jar、rmissl.jar 如果在DOS下用命令行開發,則把這五個JAR包加入到classpath系統變量中。如果你用Eclipse開發,則把JAR包加入到項目屬性的Libratries(庫)引用中。 2、JDK5.0以上 JDK5.0的jre/lib/rt.jar已經包含了jmxri.jar、jmxremote.jar、rmissl.jar三個包的代碼。如果你用到jmxtools.jar、jmxremote_optional.jar的類,則需要將這兩個類加入到classpath或Eclipse的項目庫引用中。 3、我使用的開發環境:JDK5.0 + Eclipse3.2。 注:因為用到jmxtools.jar中的HtmlAdaptorServer類,所以將此包加入到項目庫引用中。
Server端程序范例: 1. MBean接口 這是一個應用程序將要向外暴露的接口,在該接口中需要定義要公布的所有函數。 其中,如果存在一對對應的get方法和set方法,那么就默認有一個屬性,且熟悉的名字就是get方法名字中get后面的部分。 包含在MBean中方法都將是可以被管理的。MBean起名是有規范的,就是原類名后加上MBean字樣。
[java] view plaincopyprint?
package ?study.test.jmx;???? public ?interface ?HelloWorldMBean?{??????public ?String?getName();?????????? ????public ?void ?setName(String?name);?????? ????public ?void ?printHello();????????? ????public ?void ?printHello(String?whoName);???? }?? package study.test.jmx;public interface HelloWorldMBean {public String getName(); public void setName(String name); public void printHello(); public void printHello(String whoName);
}
2. 被管理的類 被管理的類需要實現相應的MBean接口,通過MBean接口中的方法來被管理。
[java] view plaincopyprint?
package ?study.test.jmx;???? public ?class ?HelloWorld?implements ?HelloWorldMBean?{???????? ????private ?String?name;?????? ?????? ????public ?String?getName()?{?????? ????????return ?name;?????? ????}?????? ????? ????public ?void ?setName(String?name)?{?????? ????????this .name?=?name;?????? ????}?????? ????? ????public ?void ?printHello()?{?????? ????????System.out.println("Hello?World,?" ?+?name);?????? ????}?????? ????? ????public ?void ?printHello(String?whoName)?{?????? ????????System.out.println("Hello?,?" ?+?whoName);?????? ????}?????? ?? }?? package study.test.jmx;public class HelloWorld implements HelloWorldMBean {private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public void printHello() { System.out.println("Hello World, " + name); } public void printHello(String whoName) { System.out.println("Hello , " + whoName); } } 3. 創建一個Agent類 Agent其實實現的是類似于Server的功能,他負責把JMX服務綁定到相應的URL,并將我們上面創建的被管理的類綁定到其中,使得外部可以訪問。
[java] view plaincopyprint?
package ?study.test.jmx;???? import ?java.io.IOException;??import ?java.rmi.registry.LocateRegistry;??import ?java.rmi.registry.Registry;???? import ?javax.management.InstanceAlreadyExistsException;??import ?javax.management.MBeanRegistrationException;??import ?javax.management.MBeanServer;??import ?javax.management.MBeanServerFactory;??import ?javax.management.MalformedObjectNameException;??import ?javax.management.NotCompliantMBeanException;??import ?javax.management.ObjectName;??import ?javax.management.remote.JMXConnectorServer;??import ?javax.management.remote.JMXConnectorServerFactory;??import ?javax.management.remote.JMXServiceURL;???? import ?com.sun.jdmk.comm.HtmlAdaptorServer;???? public ?class ?HelloWorldAgent?{???? ????public ?static ?void ?main(String[]?args)?throws ?MalformedObjectNameException,?? ????????????NullPointerException,?InstanceAlreadyExistsException,?? ????????????MBeanRegistrationException,?NotCompliantMBeanException,?IOException?{?? ?? ????????int ?rmiPort?=?1099 ;?? ????????String?jmxServerName?=?"TestJMXServer" ;?? ?????????? ?????????? ????????Registry?registry?=?LocateRegistry.createRegistry(rmiPort);?? ?? ????????MBeanServer?mbs?=?MBeanServerFactory.createMBeanServer(jmxServerName);?? ?????????? ?????? ????????HtmlAdaptorServer?adapter?=?new ?HtmlAdaptorServer();?? ????????ObjectName?adapterName;?? ????????adapterName?=?new ?ObjectName(jmxServerName?+?":name=" ?+?"htmladapter" );?? ????????adapter.setPort(8082 );?? ????????adapter.start();?? ????????mbs.registerMBean(adapter,?adapterName);?? ?? ????????ObjectName?objName?=?new ?ObjectName(jmxServerName?+?":name=" ?+?"HelloWorld" );?? ????????mbs.registerMBean(new ?HelloWorld(),?objName);?? ?????????? ?? ????????JMXServiceURL?url?=?new ?JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" ?+?rmiPort?+?"/" ?+?jmxServerName);?? ????????System.out.println("JMXServiceURL:?" ?+?url.toString());?? ????????JMXConnectorServer?jmxConnServer?=?JMXConnectorServerFactory.newJMXConnectorServer(url,?null ,?mbs);?? ????????jmxConnServer.start();?? ?? ????}?? }?? package study.test.jmx;import java.io.IOException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;import com.sun.jdmk.comm.HtmlAdaptorServer;public class HelloWorldAgent {public static void main(String[] args) throws MalformedObjectNameException,NullPointerException, InstanceAlreadyExistsException,MBeanRegistrationException, NotCompliantMBeanException, IOException {int rmiPort = 1099;String jmxServerName = "TestJMXServer";// jdkfolder/bin/rmiregistry.exe 9999 Registry registry = LocateRegistry.createRegistry(rmiPort);MBeanServer mbs = MBeanServerFactory.createMBeanServer(jmxServerName);//MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();HtmlAdaptorServer adapter = new HtmlAdaptorServer();ObjectName adapterName;adapterName = new ObjectName(jmxServerName + ":name=" + "htmladapter");adapter.setPort(8082);adapter.start();mbs.registerMBean(adapter, adapterName);ObjectName objName = new ObjectName(jmxServerName + ":name=" + "HelloWorld");mbs.registerMBean(new HelloWorld(), objName);JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + rmiPort + "/" + jmxServerName);System.out.println("JMXServiceURL: " + url.toString());JMXConnectorServer jmxConnServer = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);jmxConnServer.start();}
}
說明: 1. Agent實現中的35行到40行為MBeanServer添加了一個
htmladapter,這樣我們就可以通過網頁的方式來進行管理。 ?比如說上面我們實行的Agent,我們就可以通過http://localhost:8082來對程序進行管理。這里的8082就是htmladapter中設置的端口。 通過我們設定的MBean名字點擊去,就可以進一步來管理我們的MBean ?從這張圖我們可以看出,我們可以直接從網頁上面來改動Name的值,并且也可以直接通過點擊來調用相應的方法:printHello ? ? ?2. 如果大家在嘗試寫Agent程序時出現connection refused的異常的時候,不用怕,趕緊檢查一下你的程序中是不是有這句話: ???Registry registry = LocateRegistry.createRegistry(rmiPort); ???LocateRegistry.createRegistry(int port)方法可以在某一特定端口創建名字服務,從而用戶無需再手工啟動rmiregistry ???或者,你也可以運行? jdkfolder/bin/rmiregistry.exe 9999 ???其中jdkfolder是你的jdk的安裝目錄,9999是你要綁定的端口 ???運行上面的命令和你在代碼中添加上面那行code是一樣的效果 ??? ?3. Agent的實現中的32行和33行是兩種獲取MBeanServer的方式。 ??? MBeanServer mbs = MBeanServerFactory.createMBeanServer(jmxServerName); ??? 這種方式主要用于JDK1.5以前 ??MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); ?? 這種方式是JDK1.5引入的。 ?? 安全起見,當大家不能確定以后部署的機器上面安裝的JDK是1.5以上的版本時,建議按照第一種方式。 ?? ?4. 綁定需要被管理的類 ??? ObjectName objName = new ObjectName(jmxServerName + ":name=" + "HelloWorld"); ??mbs.registerMBean(new HelloWorld(), objName); ??這里我們可以看到,首先要給被綁定的類起一個名字,然后把這個名字和被管理的類一起注冊到MBeanServer當中。 ?? 5. 將服務綁定到固定的URL上 ??JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + rmiPort + "/" + jmxServerName); ??JMXConnectorServer jmxConnServer = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); ??jmxConnServer.start(); ??在start方法被調用后,服務就已經發布成功,我們就可以通過頁面或者其他的方式來訪問服務
?
?
===========
http://damies.iteye.com/blog/51804
前面所有看效果都是通過Html網頁來看的。JDK5.0自帶了一個jmx客戶端,叫jconsole,位于c:\jdk\bin\jconsole.exe。我們來用用這個客戶端來連接Mbean Server。 一、vm參數方式 1、還是用第一篇的那個HelloAgent,修改HelloAgent,將第一句: MBeanServer server = MBeanServerFactory.createMBeanServer(); 改為:MBeanServer server = ManagementFactory.getPlatformMBeanServer(); 注:ManagementFactory的全路徑為:java.lang.management.ManagementFactory 2、修改Eclipse的run選項,把“-Dcom.sun.management.jmxremote=HelloAgent”這一句加入到run選項中 3、運行HelloAgent,然后在Dos窗口輸入“jconsole”來啟到JConsole 4、單擊“連接” 二、RMI方式 還是用jconsole,但方式變了。這里不需要象上面那樣修改Eclipse run的vm選項。 1、還是用第一篇的HelloAgent,加上一段代碼,啟動一個JMXConnectorServer服務
java 代碼
import ?javax.management.MBeanServer; ??import ?javax.management.MBeanServerFactory; ??import ?javax.management.ObjectName; ??import ?javax.management.remote.JMXConnectorServer; ??import ?javax.management.remote.JMXConnectorServerFactory; ??import ?javax.management.remote.JMXServiceURL; ???? import ?com.sun.jdmk.comm.HtmlAdaptorServer; ???? public ?class ?HelloAgent?{ ??????public ?static ?void ?main(String?args[])?throws ?Exception?{ ?? ????????MBeanServer?server?=?MBeanServerFactory.createMBeanServer(); ?? ????????ObjectName?helloName?=?new ?ObjectName("chengang:name=HelloWorld" ); ?? ????????Hello?hello?=?new ?Hello(); ?? ????????server.registerMBean(hello,?helloName); ?? ????????ObjectName?adapterName?=?new ?ObjectName("HelloAgent:name=htmladapter,port=8082" ); ?? ????????HtmlAdaptorServer?adapter?=?new ?HtmlAdaptorServer(); ?? ????????server.registerMBean(adapter,?adapterName); ?? ????????adapter.start(); ?? ????????System.out.println("start....." ); ?? ?? ?????????? ????????JMXServiceURL?url?=?new ?JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/server" ); ?? ????????JMXConnectorServer?cs?=?JMXConnectorServerFactory.newJMXConnectorServer(url,?null ,?server); ?? ????????cs.start(); ?? ????????System.out.println("rmi start....." ); ?? ????} ?? } ?? 2、在Dos運行一個命令:rmiregistry 9999
?
3、運行HelloAgent,然后再在dos下運行命令jconsole
輸入service:jmx:rmi:///jndi/rmi://localhost:9999/server
三、總結
連接MBeanServer的方式除了Html、JConsole,還有一些第三方的客戶端,比較有名的是MC4j,通過這些客戶端我們可以很容易去訪問MBean。這也就是我們為什么要用JMX的其中一個原因:試想如果我自己搞一套標準,勢必要自己開發一個客戶端,那會是一個不小的工作量。
?
總結
以上是生活随笔 為你收集整理的我的JMX心得 -- Server端 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。