国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
Java SE 6 新特性: JMX 與系統(tǒng)管理

2006 年底,Sun 公司發(fā)布了 Java Standard Edition 6(Java SE 6)的最終正式版,代號(hào) Mustang(野馬)。跟 Tiger(Java SE 5)相比,Mustang 在性能方面有了不錯(cuò)的提升。與 Tiger 在 API 庫(kù)方面的大幅度加強(qiáng)相比,雖然 Mustang 在 API 庫(kù)方面的新特性顯得不太多,但是也提供了許多實(shí)用和方便的功能:在腳本,WebService,XML,編譯器 API,數(shù)據(jù)庫(kù),JMX,網(wǎng)絡(luò)和 Instrumentation 方面都有不錯(cuò)的新特性和功能加強(qiáng)。 本系列 文章主要介紹 Java SE 6 在 API 庫(kù)方面的部分新特性,通過(guò)一些例子和講解,幫助開(kāi)發(fā)者在編程實(shí)踐當(dāng)中更好的運(yùn)用 Java SE 6,提高開(kāi)發(fā)效率。

本文是其中的第三篇,介紹了 Java 管理擴(kuò)展(Java Management Extension,JMX) 架構(gòu)及其框架,以及在 Java SE 5 中新引入的 JMX API -- java.lang.management 包, 最后作者講述了此 API 在 Java SE 6 中的相關(guān)改進(jìn)和對(duì)未來(lái)版本的展望

前言

在 Java 程序的運(yùn)行過(guò)程中,對(duì) JVM 和系統(tǒng)的監(jiān)測(cè)一直是 Java 開(kāi)發(fā)人員在開(kāi)發(fā)過(guò)程所需要的。一直以來(lái),Java 開(kāi)發(fā)人員必須通過(guò)一些底層的 JVM API,比如 JVMPI 和 JVMTI 等,才能監(jiān)測(cè) Java 程序運(yùn)行過(guò)程中的 JVM 和系統(tǒng)的一系列情況,這種方式一直以來(lái)被人所詬病,因?yàn)檫@需要大量的 C 程序和 JNI 調(diào)用,開(kāi)發(fā)效率十分低下。于是出現(xiàn)了各種不同的專門(mén)做資源管理的程序包。為了解決這個(gè)問(wèn)題,Sun 公司也在其 Java SE 5 版本中,正式提出了 Java 管理擴(kuò)展(Java Management Extensions,JMX)用來(lái)管理檢測(cè) Java 程序(同時(shí) JMX 也在 J2EE 1.4 中被發(fā)布)。

JMX 的提出,讓 JDK 中開(kāi)發(fā)自檢測(cè)程序成為可能,也提供了大量輕量級(jí)的檢測(cè) JVM 和運(yùn)行中對(duì)象/線程的方式,從而提高了 Java 語(yǔ)言自己的管理監(jiān)測(cè)能力。





回頁(yè)首


JMX 和系統(tǒng)管理

管理系統(tǒng)(Management System)

要了解 JMX,我們就必須對(duì)當(dāng)前的 IT 管理系統(tǒng)有一個(gè)初步的了解。隨著企業(yè) IT 規(guī)模的不斷增長(zhǎng),IT 資源(IT resource)數(shù)量不斷增加,IT 資源的分布也越來(lái)越分散。可以想象,甚至對(duì)于一家只有幾百臺(tái) PC 公司的 IT 管理人員來(lái)說(shuō),分發(fā)一個(gè)安全補(bǔ)丁并且保證其在每臺(tái) PC 上的安裝,如果只依賴人工來(lái)完成那簡(jiǎn)直就是一場(chǎng)噩夢(mèng)。這樣,IT 管理系統(tǒng)就應(yīng)運(yùn)而生。

然而,CPU、網(wǎng)卡、存儲(chǔ)陣列是 IT 資源;OS、MS Office、Oracle database、IBM Websphere 也是 IT 資源。IT 管理系統(tǒng)若要對(duì)這些 IT 資源進(jìn)行管理,就必須對(duì)這些管理對(duì)象有所了解:形形色色的 IT 資源就像是說(shuō)著不同語(yǔ)言的人:Oralce 數(shù)據(jù)庫(kù)表達(dá)內(nèi)存緊張的方式和 Window XP 是絕然不同的, 而 IT 管理系統(tǒng)就像建造通天塔的經(jīng)理,必須精通所有的語(yǔ)言, 這幾乎是一個(gè)不可能完成的任務(wù)。難道 IT 管理系統(tǒng)是另外一個(gè)通天塔嗎?當(dāng)然不是!其實(shí)我們只要給每個(gè) IT 資源配個(gè)翻譯就可以了。

管理系統(tǒng)的構(gòu)架


圖 1. 管理系統(tǒng)構(gòu)架

上圖分析了管理系統(tǒng)的基本構(gòu)架模式。其中 Agent / SubAgent 起到的就是翻譯的作用:把 IT 資源報(bào)告的消息以管理系統(tǒng)能理解的方式傳送出去。

也許讀者有會(huì)問(wèn),為什么需要 Agent 和 SubAgent 兩層體系呢?這里有兩個(gè)現(xiàn)實(shí)的原因:

  1. 管理系統(tǒng)一般是一個(gè)中央控制的控制軟件,而 SubAgent 直接監(jiān)控一些資源,往往和這些資源分布在同一物理位置。當(dāng)這些 SubAgent 把狀態(tài)信息傳輸?shù)焦芾硐到y(tǒng)或者傳達(dá)管理系統(tǒng)的控制指令的時(shí)候,需要提供一些網(wǎng)絡(luò)傳輸?shù)墓δ堋?
  2. 管理系統(tǒng)的消息是有一定規(guī)范的,消息的翻譯本身是件復(fù)雜而枯燥的事情。

一般來(lái)說(shuō),管理系統(tǒng)會(huì)將同一物理分布或者功能類似的 SubAgent 分組成一組,由一個(gè)共用的 Agent 加以管理。在這個(gè) Agent 里封裝了 1 和 2 的功能。

JMX 和管理系統(tǒng)

JMX 既是 Java 管理系統(tǒng)的一個(gè)標(biāo)準(zhǔn),一個(gè)規(guī)范,也是一個(gè)接口,一個(gè)框架。圖 2 展示了 JMX 的基本架構(gòu)。


圖 2. JMX 構(gòu)架

和其它的資源系統(tǒng)一樣,JMX 是管理系統(tǒng)和資源之間的一個(gè)接口,它定義了管理系統(tǒng)和資源之間交互的標(biāo)準(zhǔn)。javax.management.MBeanServer 實(shí)現(xiàn)了 Agent 的功能,以標(biāo)準(zhǔn)的方式給出了管理系統(tǒng)訪問(wèn) JMX 框架的接口。而 javax.management.MBeans 實(shí)現(xiàn)了 SubAgent 的功能,以標(biāo)準(zhǔn)的方式給出了 JMX 框架訪問(wèn)資源的接口。而從類庫(kù)的層次上看,JMX 包括了核心類庫(kù) java.lang.managementjavax.management 包。java.lang.management 包提供了基本的 VM 監(jiān)控功能,而 javax.management 包則向用戶提供了擴(kuò)展功能。





回頁(yè)首


JMX 的基本框架

JMX 使用了 Java Bean 模式來(lái)傳遞信息。一般說(shuō)來(lái),JMX 使用有名的 MBean,其內(nèi)部包含了數(shù)據(jù)信息,這些信息可能是:應(yīng)用程序配置信息、模塊信息、系統(tǒng)信息、統(tǒng)計(jì)信息等。另外,MBean 也可以設(shè)立可讀寫(xiě)的屬性、直接操作某些函數(shù)甚至啟動(dòng) MBean 可發(fā)送的 notification 等。MBean 包括 Standard,MXBean,Dynamic,Model,Open 等幾種分類,其中最簡(jiǎn)單是標(biāo)準(zhǔn) MBean 和 MXBean,而我們使用得最多的也是這兩種。MXBean 主要是 java.lang.management 使用較多,將在下一節(jié)中介紹。我們先了解其他一些重要的 MBean 的種類。

標(biāo)準(zhǔn) MBean

標(biāo)準(zhǔn) MBean 是最簡(jiǎn)單的一類 MBean,與動(dòng)態(tài) Bean 不同,它并不實(shí)現(xiàn) javax.management 包中的特殊的接口。說(shuō)它是標(biāo)準(zhǔn) MBean, 是因?yàn)槠湎蛲獠抗_(kāi)其接口的方法和普通的 Java Bean 相同,是通過(guò) lexical,或者說(shuō) coding convention 進(jìn)行的。下面我們就用一個(gè)例子來(lái)展現(xiàn),如何實(shí)現(xiàn)一個(gè)標(biāo)準(zhǔn) MBean 來(lái)監(jiān)控某個(gè)服務(wù)器 ServerImpl 狀態(tài)的。ServerImpl 代表了用來(lái)演示的某個(gè) Server 的實(shí)現(xiàn):

package standardbeans;                        public class ServerImpl {                        public final long startTime;                        public ServerImpl() {                        startTime = System.currentTimeMillis();                        }                        }                        

然后,我們打算使用一個(gè)標(biāo)準(zhǔn) MBean,ServerMonitor 來(lái)監(jiān)控 ServerImpl:

package standardbeans;                        public class ServerMonitor implements ServerMonitorMBean {                        private final ServerImpl target;                        public ServerMonitor(ServerImpl target){                        this.target = target;                        }                        public long getUpTime(){                        return System.currentTimeMillis() - target.startTime;                        }                        }                        

這里的 ServerMonitorBean 又是怎么回事呢?MXBean 規(guī)定了標(biāo)準(zhǔn) MBean 也要實(shí)現(xiàn)一個(gè)接口,所有向外界公開(kāi)的方法都要在這個(gè)接口中聲明。否則,管理系統(tǒng)就不能從中獲得相應(yīng)的信息。此外,該接口的名字也有一定的規(guī)范:即在標(biāo)準(zhǔn) MBean 類名之后加上“MBean”后綴。若 MBean 的類名叫做 MBeansName 的話,對(duì)應(yīng)的接口就要叫做 MBeansNameMBean。

對(duì)于管理系統(tǒng)來(lái)說(shuō),這些在 MBean 中公開(kāi)的方法,最終會(huì)被 JMX 轉(zhuǎn)化成屬性(Attribute)、監(jiān)聽(tīng)(Listener)和調(diào)用(Invoke)的概念。如果讀者對(duì) Java Bean 有一些了解的話,不難看出,public long getUpTime() 對(duì)應(yīng)了 Bean 中的一個(gè)稱為“upTime”的只讀屬性。

下面我們就看一個(gè)模擬管理系統(tǒng)的例子:

package standardbeans;                        import javax.management.MBeanServer;                        import javax.management.MBeanServerFactory;                        import javax.management.ObjectName;                        public class Main {                        private static ObjectName objectName ;                        private static MBeanServer mBeanServer;                        public static void main(String[] args) throws Exception{                        init();                        manage();                        }                        private static void init() throws Exception{                        ServerImpl serverImpl = new ServerImpl();                        ServerMonitor serverMonitor = new ServerMonitor(serverImpl);                        mBeanServer = MBeanServerFactory.createMBeanServer();                        objectName = new ObjectName("objectName:id=ServerMonitor1");                        mBeanServer.registerMBean(serverMonitor,objectName);                        }                        private static void manage() throws Exception{                        Long upTime = (Long) mBeanServer.getAttribute(objectName,                        "upTime");                        System.out.println(upTime);                        }                        }                        

JMX 的核心是 MBServer。Java SE 已經(jīng)提供了一個(gè)默認(rèn)實(shí)現(xiàn),可以通過(guò) MBServerFactory.createMBeanServer() 獲得。每個(gè)資源監(jiān)控者(MBean)一般都會(huì)有名稱(ObjectName), 登記在 MBServer 內(nèi)部的一個(gè) Repository 中。注意,這個(gè) ObjectName 對(duì)于每一個(gè) MBServer 必須是唯一的,只能對(duì)應(yīng)于一個(gè) MBean。(讀者有興趣的話,可以試著再給 mBeanServer 注冊(cè)一個(gè)同名的 objectName,看看會(huì)怎么樣。) 上述例子是在 init() 方法中完成向 MBeanServer 注冊(cè)工作的。

在管理過(guò)程中,管理系統(tǒng)并不與資源或者 SubAgent 直接打交道,也就是說(shuō),這里不會(huì)直接引用到 MBean。而是通過(guò) MBeanServer 的 getAttribute 方法取得對(duì)應(yīng) MBean 的屬性的。

動(dòng)態(tài) MBean

但是對(duì)于很多已有的 SubAgent 實(shí)現(xiàn),其 Coding Convention 并不符合標(biāo)準(zhǔn) MBean 的要求。重構(gòu)所有這些 SubAgent 以符合標(biāo)準(zhǔn) MBean 標(biāo)準(zhǔn)既費(fèi)力也不實(shí)際。JMX 中給出了動(dòng)態(tài)(Dynamic) MBean 的概念,MBServer 不再依據(jù) Coding Convention 而是直接查詢動(dòng)態(tài) MBean 給出的元數(shù)據(jù)(meta data)以獲得 MBean 的對(duì)外接口。

package dynamicbeans;                        import javax.management.*;                        import java.lang.reflect.*;                        public class ServerMonitor implements DynamicMBean {                        private final ServerImpl target;                        private MBeanInfo mBeanInfo;                        public ServerMonitor(ServerImpl target){                        this.target = target;                        }                        //實(shí)現(xiàn)獲取被管理的 ServerImpl 的 upTime                        public long upTime(){                        return System.currentTimeMillis() - target.startTime;                        }                        //javax.management.MBeanServer 會(huì)通過(guò)查詢 getAttribute("Uptime") 獲得 "Uptime" 屬性值                        public Object getAttribute(String attribute) throws AttributeNotFoundException,                        MBeanException, ReflectionException {                        if(attribute.equals("UpTime")){                        return upTime();                        }                        return null;                        }                        //給出 ServerMonitor 的元信息。                        public MBeanInfo getMBeanInfo() {                        if (mBeanInfo == null) {                        try {                        Class cls = this.getClass();                        //用反射獲得 "upTime" 屬性的讀方法                        Method readMethod = cls.getMethod("upTime", new Class[0]);                        //用反射獲得構(gòu)造方法                        Constructor constructor = cls.getConstructor(new Class[]                        {ServerImpl.class});                        //關(guān)于 "upTime" 屬性的元信息:名稱為 UpTime,只讀屬性(沒(méi)有寫(xiě)方法)。                        MBeanAttributeInfo upTimeMBeanAttributeInfo = new MBeanAttributeInfo(                        "UpTime", "The time span since server start",                        readMethod, null);                        //關(guān)于構(gòu)造函數(shù)的元信息                        MBeanConstructorInfo mBeanConstructorInfo = new MBeanConstructorInfo(                        "Constructor for ServerMonitor", constructor);                        //ServerMonitor 的元信息,為了簡(jiǎn)單起見(jiàn),在這個(gè)例子里,                        //沒(méi)有提供 invocation 以及 listener 方面的元信息                        mBeanInfo = new MBeanInfo(cls.getName(),                        "Monitor that controls the server",                        new MBeanAttributeInfo[] { upTimeMBeanAttributeInfo },                        new MBeanConstructorInfo[] { mBeanConstructorInfo },                        null, null);                        } catch (Exception e) {                        throw new Error(e);                        }                        }                        return mBeanInfo;                        }                        public AttributeList getAttributes(String[] arg0) {                        return null;                        }                        public Object invoke(String arg0, Object[] arg1, String[] arg2)                        throws MBeanException,                        ReflectionException {                        return null;                        }                        public void setAttribute(Attribute arg0) throws AttributeNotFoundException,                        InvalidAttributeValueException, MBeanException, ReflectionException {                        return;                        }                        public AttributeList setAttributes(AttributeList arg0) {                        return null;                        }                        }                        

其它動(dòng)態(tài) MBean

另外還有兩類 MBean:Open MBean 和 Model MBean。實(shí)際上它們也都是動(dòng)態(tài) MBean。

Open MBean 與其它動(dòng)態(tài) MBean 的唯一區(qū)別在于,前者對(duì)其公開(kāi)接口的參數(shù)和返回值有所限制 —— 只能是基本類型或者 javax.management.openmbean 包內(nèi)的 ArrayType、CompositeType、TarbularType 等類型。這主要是考慮到管理系統(tǒng)的分布,很可能遠(yuǎn)端管理系統(tǒng)甚至 MBServer 層都不具有 MBean 接口中特殊的類。

Model Bean

然而,普通的動(dòng)態(tài) Bean 通常缺乏一些管理系統(tǒng)所需要的支持:比如持久化 MBean 的狀態(tài)、日志記錄、緩存等等。如果讓用戶去一一實(shí)現(xiàn)這些功能確實(shí)是件枯燥無(wú)聊的工作。為了減輕用戶的負(fù)擔(dān),JMX 提供商都會(huì)提供不同的 ModelBean 實(shí)現(xiàn)。其中有一個(gè)接口是 Java 規(guī)范中規(guī)定所有廠商必須實(shí)現(xiàn)的:javax.management.modelmbean.RequiredModelBean。通過(guò)配置 Descriptor 信息,我們可以定制這個(gè) Model Bean, 指定哪些 MBean 狀態(tài)需要記入日志、如何記錄以及是否緩存某些屬性、緩存多久等等。這里,我們以 RequiredModelBean 為例討論 ModelBean。比如,我們先來(lái)看一個(gè)例子,首先是 server 端:

package modelmbean;                        public class Server {                        private long startTime;                        public Server() {	}                        public int start(){                        startTime = System.currentTimeMillis();                        return 0;                        }                        public long getUpTime(){                        return System.currentTimeMillis() - startTime;                        }                        }                        

然后我們對(duì)它的監(jiān)測(cè)如下:

package modelmbean;                        import javax.management.*;                        import javax.management.modelmbean.*;                        public class Main {                        public static void main(String[] args) throws Exception{                        MBeanServer mBeanServer = MBeanServerFactory.createMBeanServer();                        RequiredModelMBean serverMBean =                        (RequiredModelMBean) mBeanServer.instantiate(                        "javax.management.modelmbean.RequiredModelMBean");                        ObjectName serverMBeanName =                        new ObjectName("server: id=Server");                        serverMBean.setModelMBeanInfo(getModelMBeanInfoForServer(serverMBeanName));                        Server server = new Server();                        serverMBean.setManagedResource(server, "ObjectReference");                        ObjectInstance registeredServerMBean =                        mBeanServer.registerMBean((Object) serverMBean, serverMBeanName);                        serverMBean.invoke("start",null, null);                        Thread.sleep(1000);                        System.out.println(serverMBean.getAttribute("upTime"));                        Thread.sleep(5000);                        System.out.println(serverMBean.getAttribute("upTime"));                        }                        private static ModelMBeanInfo getModelMBeanInfoForServer(ObjectName objectName)                        throws Exception{                        ModelMBeanAttributeInfo[] serverAttributes =                        new ModelMBeanAttributeInfo[1];                        Descriptor upTime =                        new DescriptorSupport(                        new String[] {                        "name=upTime",                        "descriptorType=attribute",                        "displayName=Server upTime",                        "getMethod=getUpTime",                        });                        serverAttributes[0] =                        new ModelMBeanAttributeInfo(                        "upTime",                        "long",                        "Server upTime",                        true,                        false,                        false,                        upTime);                        ModelMBeanOperationInfo[] serverOperations =                        new ModelMBeanOperationInfo[2];                        Descriptor getUpTimeDesc =                        new DescriptorSupport(                        new String[] {                        "name=getUpTime",                        "descriptorType=operation",                        "class=modelmbean.Server",                        "role=operation"                        });                        MBeanParameterInfo[] getUpTimeParms = new MBeanParameterInfo[0];                        serverOperations[0] = new ModelMBeanOperationInfo("getUpTime",                        "get the up time of the server",                        getUpTimeParms,                        "java.lang.Long",                        MBeanOperationInfo.ACTION,                        getUpTimeDesc);                        Descriptor startDesc =                        new DescriptorSupport(                        new String[] {                        "name=start",                        "descriptorType=operation",                        "class=modelmbean.Server",                        "role=operation"                        });                        MBeanParameterInfo[] startParms = new MBeanParameterInfo[0];                        serverOperations[1] = new ModelMBeanOperationInfo("start",                        "start(): start server",                        startParms,                        "java.lang.Integer",                        MBeanOperationInfo.ACTION,                        startDesc);                        ModelMBeanInfo serverMMBeanInfo =                        new ModelMBeanInfoSupport(                        "modelmbean.Server",                        "ModelMBean for managing an Server",                        serverAttributes,                        null,                        serverOperations,                        null);                        //Default strategy for the MBean.                        Descriptor serverDescription =                        new DescriptorSupport(                        new String[] {                        ("name=" + objectName),                        "descriptorType=mbean",                        ("displayName=Server"),                        "type=modelmbean.Server",                        "log=T",                        "logFile=serverMX.log",                        "currencyTimeLimit=10" });                        serverMMBeanInfo.setMBeanDescriptor(serverDescription);                        return serverMMBeanInfo;                        }                        

很明顯,和其它 MBean 類似,使用 Model MBean 的過(guò)程也是下面幾步:

  1. 創(chuàng)建一個(gè) MBServer:mBeanServe
  2. 獲得管理資源用的 MBean:serverBean
  3. 給這個(gè) MBean 一個(gè) ObjectName:serverMBeanName
  4. 將 serverBean 以 serverMBeanName 注冊(cè)到 mBeanServer 上去

唯一不同的是,ModelMBean 需要額外兩步:

1.serverMBean.setModelMBeanInfo(getModelMBeanInfoForServer(serverMBeanName));                        2.serverMBean.setManagedResource(server, "ObjectReference");                        

第一步用于提供 serverMBean 的元數(shù)據(jù),主要包括以下兩類

  1. 類似于普通的動(dòng)態(tài) MBean,需要 MBean 的 Attribute、Invocation、Notification 的類型/反射信息,諸如返回類型、參數(shù)類型和相關(guān)的 get/set 方法等。這里將不再贅述。
  2. 關(guān)于緩存、持久化以及日志等的策略。后面我們將介紹一些這方面的信息。

第二步指出了 ServerMBean 管理的對(duì)象,也就是說(shuō),從元數(shù)據(jù)中得到的 Method 將施加在哪個(gè) Object 上。需要指出的是 setManagedResource(Object o, String type); 中第二個(gè)參數(shù)是 Object 類型,可以是 "ObjectReference"、"Handle"、"IOR"、"EJBHandle" 或 "RMIReference"。目前 SE 中的實(shí)現(xiàn)只支持 "ObjectReference"。筆者認(rèn)為后面幾種類型是為了將來(lái) JMX 管理對(duì)象擴(kuò)展而設(shè)定的,可能將來(lái) Model Bean 不僅可以管理 Plain Java Object(POJO),還可能管理 Native Resource, 并給諸如 EJB 和 RMI 對(duì)象的管理提供更多的特性。

Model Bean 與普通動(dòng)態(tài) Bean 區(qū)別在于它的元數(shù)據(jù)類型 ModelMBeanInfo 擴(kuò)展了前者的 MBeanInfo,使得 ModelMBeanOperationInfo、ModelMBeanConstructor_Info、ModelMBeanAttributeInfo 和 ModelMBeanNotificationInfo 都有一個(gè)額外的元數(shù)據(jù):javax.management.Descriptor,它是用來(lái)設(shè)定 Model Bean 策略的。數(shù)據(jù)的存儲(chǔ)是典型的 "key-value" 鍵值對(duì)。不同的 Model Bean 實(shí)現(xiàn),以及不同的 MBeanFeatureInfo 支持不同的策略特性。下面我們就以 Attribute 為例,看一下 RequiredModelBean 支持的策略。

首先,它最重要的 Descriptor 主要是 name、displayName 和 descriptorType,其中 name 是屬性名稱。"name" 要與對(duì)應(yīng) ModelMBeanAttributeInfo 的 name 相同。descriptorType 必須是 "attribute"。

另外,value、default、legalValues "value" 是用來(lái)設(shè)定初始值的,"default" 指當(dāng)不能從 resource 中獲得該屬性時(shí)的默認(rèn)返回值,"legalValues" 是一組合法的屬性數(shù)據(jù)。它并不用來(lái)保證 setAttribute 的數(shù)據(jù)一致性,而是在 UI 系統(tǒng),如 JConsole 中提示用戶可能的數(shù)據(jù)輸入。

在屬性訪問(wèn)的 getMethod, setMethod 方法上,事實(shí)上所有對(duì)屬性的訪問(wèn)都會(huì)被 delegate 給同一 MBeanInfo 中特定的 Operation。 getMethod/setMethod 給出了對(duì)應(yīng)的 ModelMBeanOperationInfo 名稱。

還有一些額外的屬性,比如:persistPolicy, persistPeriod 是代表了持久化策略;currencyTimeLimit, lastUpdatedTimeStamp 緩存策略;iterable 屬性是否必須使用 iterate 來(lái)訪問(wèn)。默認(rèn)為否;protocolMap 定義了與第三方系統(tǒng)有關(guān)的數(shù)據(jù)轉(zhuǎn)換的 data model;visibility 定義了與第三方 UI 系統(tǒng)有關(guān)的 MBean 如何顯示的策略;presentationString 也是定義了與第三方 UI 系統(tǒng)有關(guān)的 MBean 如何顯示策略,比如 "presentation=server.gif"。

事實(shí)上,策略特性有兩個(gè)層次的作用域:整個(gè) Model Bean 和特定的 MBeanFeature。

Model Bean 的策略描述會(huì)被施加到該 Model Bean 的所有 MBeanFeature 上去,除非該 MBeanFeature 重寫(xiě)了這個(gè)策略特性。

在上面的例子里,這一個(gè)語(yǔ)句:

	serverMMBeanInfo.setMBeanDescriptor(serverDescription);                        

給整個(gè) serverMBeanInfo 設(shè)了一個(gè)策略描述 serverDescription,其中用 "currencyTimeLimit=10" 指出屬性的緩存時(shí)間是 10 秒。所以,在 Main 方法中,兩次 serverMBean.getAttribute("upTime");之間的間隔小于 10 秒就會(huì)得到同樣的緩存值。

如果我們不想讓 "upTime" 這個(gè)屬性被緩存,我們可以在它的策略描述中加入 "currencyTimeLimit=-1":

Descriptor upTime =    new DescriptorSupport(                        new String[] {                        "name=upTime",                        "descriptorType=attribute",                        "displayName=Server upTime",                        "getMethod=getUpTime",                        "currencyTimeLimit=-1" //不需要緩存                        });                        Descriptor getUpTimeDesc =                        new DescriptorSupport(                        new String[] {                        "name=getUpTime",                        "descriptorType=operation",                        "class=modelmbean.Server",                        "role=operation"                        ,"currencyTimeLimit=-1" //不需要緩存                        });                        

getUpTimeDesc 也要改動(dòng)的原因是 RequiredModelBean 會(huì)把獲取 upTime 屬性的工作 delegate 給 getUpTime invocation。只要其中一處使用 MBean 級(jí)的緩存策略,就沒(méi)法獲得實(shí)時(shí) upTime 數(shù)據(jù)了。





回頁(yè)首


虛擬機(jī)檢測(cè)

JMX 與虛擬機(jī)檢測(cè)

JMX 的提出,為 Java 虛擬機(jī)提供了 Java 層上的檢測(cè)機(jī)制。J2SE 中,新提出的 java.lang.management 包即是 JMX 在 JDK 的一個(gè)應(yīng)用,它提供了大量的有用的接口,通過(guò) MBean 方式,提供了對(duì) Java 虛擬機(jī)和運(yùn)行時(shí)遠(yuǎn)端的監(jiān)控和檢測(cè)方式,來(lái)幫助用戶來(lái)檢測(cè)本地或者遠(yuǎn)端的虛擬機(jī)的運(yùn)行情況。有了 JMX 之后,我們可以設(shè)計(jì)一個(gè)客戶端,來(lái)檢測(cè)遠(yuǎn)端一個(gè)正在運(yùn)行的虛擬機(jī)中的線程數(shù)、線程當(dāng)前的 Stack、內(nèi)存管理、GC 所占用的時(shí)間、虛擬機(jī)中的對(duì)象和當(dāng)前虛擬機(jī)參數(shù)等重要的參數(shù)和運(yùn)行時(shí)信息。JMX 另外的一個(gè)重要功能是對(duì)配置信息的檢測(cè)和再配置。比如,我們可以在遠(yuǎn)端查看和修改當(dāng)前 JVM 的 verbose 參數(shù),以達(dá)到動(dòng)態(tài)管理的目的。甚至,我們可以在遠(yuǎn)端指揮 JVM 做一次 GC,這在下文中有詳細(xì)介紹。

JMX 提供的虛擬機(jī)檢測(cè) API

檢測(cè)虛擬機(jī)當(dāng)前的狀態(tài)總是 Java 開(kāi)放人員所關(guān)心的,也正是因?yàn)槿绱?,出現(xiàn)了大量的 profiler 工具來(lái)檢測(cè)當(dāng)前的虛擬機(jī)狀態(tài)。從 Java SE 5 之后,在 JDK 中,我們有了一些 Java 的虛擬機(jī)檢測(cè) API,即 java.lang.management 包。Management 包里面包括了許多 MXBean 的接口類和 LockInfo、MemoryUsage、MonitorInfo 和 ThreadInfo 等類。從名字可以看出,該包提供了虛擬機(jī)內(nèi)存分配、垃圾收集(GC)情況、操作系統(tǒng)層、線程調(diào)度和共享鎖,甚至編譯情況的檢測(cè)機(jī)制。這樣一來(lái),Java 的開(kāi)發(fā)人員就可以很簡(jiǎn)單地為自己做一些輕量級(jí)的系統(tǒng)檢測(cè),來(lái)確定當(dāng)前程序的各種狀態(tài),以便隨時(shí)調(diào)整。

要獲得這些信息,我們首先通過(guò) java.lang.management.ManagementFactory 這個(gè)工廠類來(lái)獲得一系列的 MXBean。包括:

  • ClassLoadingMXBean

    ClassLoadMXBean 包括一些類的裝載信息,比如有多少類已經(jīng)裝載/卸載(unloaded),虛擬機(jī)類裝載的 verbose 選項(xiàng)(即命令行中的 Java –verbose:class 選項(xiàng))是否打開(kāi),還可以幫助用戶打開(kāi)/關(guān)閉該選項(xiàng)。

  • CompilationMXBean

    CompilationMXBean 幫助用戶了解當(dāng)前的編譯器和編譯情況,該 mxbean 提供的信息不多。

  • GarbageCollectorMXBean

    相對(duì)于開(kāi)放人員對(duì) GC 的關(guān)注程度來(lái)說(shuō),該 mxbean 提供的信息十分有限,僅僅提供了 GC 的次數(shù)和 GC 花費(fèi)總時(shí)間的近似值。但是這個(gè)包中還提供了三個(gè)的內(nèi)存管理檢測(cè)類:MemoryManagerMXBean,MemoryMXBean 和 MemoryPoolMXBean。

    • MemoryManagerMXBean

      這個(gè)類相對(duì)簡(jiǎn)單,提供了內(nèi)存管理類和內(nèi)存池(memory pool)的名字信息。

    • MemoryMXBean

      這個(gè)類提供了整個(gè)虛擬機(jī)中內(nèi)存的使用情況,包括 Java 堆(heap)和非 Java 堆所占用的內(nèi)存,提供當(dāng)前等待 finalize 的對(duì)象數(shù)量,它甚至可以做 gc(實(shí)際上是調(diào)用 System.gc)。

    • MemoryPoolMXBean

      該信息提供了大量的信息。在 JVM 中,可能有幾個(gè)內(nèi)存池,因此有對(duì)應(yīng)的內(nèi)存池信息,因此,在工廠類中,getMemoryPoolMXBean() 得到是一個(gè) MemoryPoolMXBean 的 list。每一個(gè) MemoryPoolMXBean 都包含了該內(nèi)存池的詳細(xì)信息,如是否可用、當(dāng)前已使用內(nèi)存/最大使用內(nèi)存值、以及設(shè)置最大內(nèi)存值等等。

  • OperatingSystemMXBean

    該類提供的是操作系統(tǒng)的簡(jiǎn)單信息,如構(gòu)架名稱、當(dāng)前 CPU 數(shù)、最近系統(tǒng)負(fù)載等。

  • RuntimeMXBean

    運(yùn)行時(shí)信息包括當(dāng)前虛擬機(jī)的名稱、提供商、版本號(hào),以及 classpath、bootclasspath 和系統(tǒng)參數(shù)等等。

  • ThreadMXBean

    在 Java 這個(gè)多線程的系統(tǒng)中,對(duì)線程的監(jiān)控是相當(dāng)重要的。ThreadMXBean 就是起到這個(gè)作用。ThreadMXBean 可以提供的信息包括各個(gè)線程的各種狀態(tài),CPU 占用情況,以及整個(gè)系統(tǒng)中的線程狀況。從 ThreadMXBean 可以得到某一個(gè)線程的 ThreadInfo 對(duì)象。這個(gè)對(duì)象中則包含了這個(gè)線程的所有信息。

java.lang.management 和虛擬機(jī)的關(guān)系

我們知道,management 和底層虛擬機(jī)的關(guān)系是非常緊密的。其實(shí),有一些的是直接依靠虛擬機(jī)提供的公開(kāi) API 實(shí)現(xiàn)的,比如 JVMTI;而另外一些則不然,很大一塊都是由虛擬機(jī)底層提供某些不公開(kāi)的 API / Native Code 提供的。這樣的設(shè)計(jì)方式,保證了 management 包可以提供足夠的信息,并且使這些信息的提供又有足夠的效率;也使 management 包和底層的聯(lián)系非常緊密。





回頁(yè)首


Java 6 中的 API 改進(jìn)

Management 在 Java SE 5 被提出之后,受到了歡迎。在 Java 6 當(dāng)中,這個(gè)包提供更多的 API 來(lái)更好地提供信息。

OperatingSystemMXBean. getSystemLoadAverage()

Java 程序通常關(guān)注是虛擬機(jī)內(nèi)部的負(fù)載、內(nèi)存等狀況,而不考慮整個(gè)系統(tǒng)的狀況。但是很多情況下,Java 程序在運(yùn)行過(guò)程中,整個(gè)計(jì)算機(jī)系統(tǒng)的系統(tǒng)負(fù)荷情況也會(huì)對(duì)虛擬機(jī)造成一定的影響。隨著 Java 的發(fā)展,Java 程序已經(jīng)覆蓋了各個(gè)行業(yè),這一點(diǎn)也必須得到關(guān)注。在以前,利用 Native 代碼來(lái)檢測(cè)系統(tǒng)負(fù)載往往是唯一的選擇,但是在 Java 6 當(dāng)中,JDK 自己提供了一個(gè)輕量級(jí)的系統(tǒng)負(fù)載檢測(cè) API,即 OperatingSystemMXBean.getSystemLoadAverage()。

當(dāng)然這個(gè) API 事實(shí)上僅僅返回一個(gè)對(duì)前一分鐘系統(tǒng)負(fù)載的簡(jiǎn)單的估測(cè)。它設(shè)計(jì)的主要目標(biāo)是簡(jiǎn)單快速地估測(cè)當(dāng)前系統(tǒng)負(fù)荷,因此它首先保證了這個(gè) API 的效率是非常高的;也因?yàn)槿绱?,這個(gè) API 事實(shí)上并不適用于所有的系統(tǒng)。

鎖檢測(cè)

我們知道,同步是 Java 語(yǔ)言很重要的一個(gè)特性。在 Java SE 中,最主要的同步機(jī)制是依靠 synchronize 關(guān)鍵字對(duì)某一個(gè)對(duì)象加鎖實(shí)現(xiàn)的;在 Java SE 5 之后的版本中,concurrent 包的加入,大大強(qiáng)化了 Java 語(yǔ)言的同步能力,concurrent 提供了很多不同類型的鎖機(jī)制可供擴(kuò)展。因此,要更好地觀測(cè)當(dāng)前的虛擬機(jī)狀況和不同線程的運(yùn)行態(tài),去觀察虛擬機(jī)中的各種鎖,以及線程與鎖的關(guān)系是非常必要的。很可惜的是,在過(guò)去的 JDK 中,我們并沒(méi)有非常方便的 API 以供使用。一個(gè)比較直接的檢測(cè)方式是查看線程的 stack trace,更為強(qiáng)大全面(但是也更復(fù)雜并且效率低下)的方案是得到一個(gè) VM 所有對(duì)象的快照并查找之,這些策略的代價(jià)都比較大,而且往往需要編寫(xiě)復(fù)雜的 Native 代碼。

JDK 6 里提供了一些相當(dāng)簡(jiǎn)單的 API 來(lái)提供這個(gè)服務(wù)。首先了解兩個(gè)新類,LockInfo 和 MonitorInfo 這兩個(gè)類承載了鎖的信息。LockInfo 可以是任何的 Java 鎖,包括簡(jiǎn)單 Java 鎖和 java.util.concurrent 包中所使用的鎖(包括 AbstractOwnableSynchronizer 和 Condition 的實(shí)現(xiàn)類/子類),而 MonitorInfo 是簡(jiǎn)單的 Java 對(duì)象所代表的鎖。要檢測(cè)一個(gè)線程所擁有的鎖和等待的鎖,首先,要得到一個(gè)線程的 ThreadInfo,然后可以簡(jiǎn)單地調(diào)用:

  • getLockedMonitors()

    返回一個(gè)所有當(dāng)前線程已經(jīng)掌握的鎖對(duì)象的列表。

  • getLockedSynchronizers()

    對(duì)于使用 concurrent 包的線程,返回一個(gè)該線程所掌握的“ownable synchronizer”(即 AbstractOwnableSynchronizer 及其子類)所組成的列表。

  • getLockInfo()

    當(dāng)前線程正在等待的那個(gè)鎖對(duì)象的信息就可以知道線程所有的鎖信息。通過(guò)這些鎖信息,我們很方便的可以知道當(dāng)前虛擬機(jī)的所有線程的鎖信息。由此,我們還可以推導(dǎo)出更多的信息。

死鎖檢測(cè)

死鎖檢測(cè)一直以來(lái)是軟件工程師所重視的,顯然一個(gè)死鎖的系統(tǒng)永遠(yuǎn)是工程師最大的夢(mèng)魘。Java 程序的死鎖檢測(cè)也一直以來(lái)是 Java 程序員所頭痛的。為了解決線程間死鎖問(wèn)題,一般都有預(yù)防(代碼實(shí)現(xiàn)階段)和死鎖后恢復(fù)(運(yùn)行時(shí))兩種方式。以前 Java 程序員都重視前者,因?yàn)樵谶\(yùn)行態(tài)再來(lái)檢測(cè)和恢復(fù)系統(tǒng)是相當(dāng)麻煩的,缺少許多必要的信息;但是,對(duì)于一些比較復(fù)雜的系統(tǒng),采取后者或者運(yùn)行時(shí)調(diào)試死鎖信息也是非常重要的。由上面所說(shuō),現(xiàn)在我們已經(jīng)可以知道每一個(gè)線程所擁有和等待的鎖,因此要計(jì)算出當(dāng)前系統(tǒng)中是否有死鎖的線程也是可行的了。當(dāng)然,Java 6 里面也提供了一個(gè) API 來(lái)完成這個(gè)功能,即:

  • ThreadMXBean.findDeadlockedThreads()

    這個(gè)函數(shù)的功能就是檢測(cè)出當(dāng)前系統(tǒng)中已經(jīng)死鎖的線程。當(dāng)然,這個(gè)功能復(fù)雜,因此比較費(fèi)時(shí)?;旧蟽H僅將之用于調(diào)試,以便對(duì)復(fù)雜系統(tǒng)線程調(diào)用的改進(jìn)。





回頁(yè)首


未來(lái)的發(fā)展

JMX 在 Java SE 5/6 中的功能已經(jīng)相當(dāng)強(qiáng)大,但是距離 Java 程序開(kāi)發(fā)人員的要求還是有一段距離,因此 Sun 公司已經(jīng)向 JCP 提出了 JSR 255 (JMX API 2.0 版本)來(lái)擴(kuò)充和進(jìn)一步發(fā)展 JMX,并希望這個(gè) JSR 將在 Java SE 7 中實(shí)現(xiàn)。在這個(gè)文檔中,新的 JMX 2.0 將著重于:

  • 對(duì) management 模型的優(yōu)化,并提供更好的支持;加入了比如 annotation 等等的新特性;
  • 對(duì) JMX 定義的優(yōu)化,在進(jìn)一步強(qiáng)化 MBean 擴(kuò)充性好的優(yōu)點(diǎn)的同時(shí),盡量改變(用戶普遍認(rèn)為的)MBean 很難實(shí)現(xiàn)的缺點(diǎn);
  • 對(duì)非 Java 平臺(tái)客戶端的支持。這將是一個(gè)令人振奮的新特性;

具體的擴(kuò)展可能包括:

  • 層次性的命名域(Hierarchical namespace);
  • 新的事件服務(wù)功能;
  • 對(duì) locales 的新支持;
  • 為 MBean 啟用 annotation 服務(wù);
  • 也可以使用用戶類型的 mapping 了;

可以看到,JMX 的進(jìn)一步發(fā)展主要關(guān)注的是可擴(kuò)展性、動(dòng)態(tài)性和易用性等 Java 用戶非常關(guān)注的方面。





回頁(yè)首


總結(jié)

在 Java SE 5 出現(xiàn)的 JMX 在 Java SE 6 中有了更多的功能和擴(kuò)展能力,這很好地適應(yīng)了 Java 語(yǔ)言的發(fā)展和用戶的要求,讓 Java 的監(jiān)測(cè)、管理的的功能更加強(qiáng)大。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
[JMX一步步來(lái)] 1、JMX的Hello World
JMX-Java Management Extensions 簡(jiǎn)單示例
JMX IN ACTION---第二章
JMX使用指南
jconsole工具介紹(二)
JVM(7):JVM 調(diào)優(yōu) - 工具篇
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服