JMX 和系统管理



    在 Java 程序的运行过程中,对 JVM 和系统的监测一直是 Java 开发人员在开发过程所需要的。一直以来,Java 开发人员必须通过一些底层的 JVM API,比如 JVMPI 和 JVMTI 等,才能监测 Java 程序运行过程中的 JVM 和系统的一系列情况,这种方式一直以来被人所诟病,因为这需要大量的 C 程序和 JNI 调用,开发效率十分低下。于是出现了各种不同的专门做资源管理的程序包。为了解决这个问题,Sun 公司也在其 Java SE 5 版本中,正式提出了 Java 管理扩展(Java Management Extensions,JMX)用来管理检测 Java 程序(同时 JMX 也在 J2EE 1.4 中被发布)。

JMX 的提出,让 JDK 中开发自检测程序成为可能,也提供了大量轻量级的检测 JVM 和运行中对象/线程的方式,从而提高了 Java 语言自己的管理监测能力。

JMX 和系统管理

管理系统(Management System)

    要了解 JMX,我们就必须对当前的 IT 管理系统有一个初步的了解。随着企业 IT 规模的不断增长,IT 资源(IT resource)数量不断增加,IT 资源的分布也越来越分散。可以想象,甚至对于一家只有几百台 PC 公司的 IT 管理人员来说,分发一个安全补丁并且保证其在每台 PC 上的安装,如果只依赖人工来完成那简直就是一场噩梦。这样,IT 管理系统就应运而生。

然而,CPU、网卡、存储阵列是 IT 资源;OS、MS Office、Oracle database、IBM Websphere 也是 IT 资源。IT 管理系统若要对这些 IT 资源进行管理,就必须对这些管理对象有所了解:形形色色的 IT 资源就像是说着不同语言的人:Oralce 数据库表达内存紧张的方式和 Window XP 是绝然不同的, 而 IT 管理系统就像建造通天塔的经理,必须精通所有的语言,这几乎是一个不可能完成的任务。难道 IT 管理系统是另外一个通天塔吗?当然不是!其实我们只要给每个 IT 资源配个翻译就可以了。

管理系统的构架


图 1. 管理系统构架



上图分析了管理系统的基本构架模式。其中 Agent / SubAgent 起到的就是翻译的作用:把 IT 资源报告的消息以管理系统能理解的方式传送出去。


也许读者有会问,为什么需要 Agent 和 SubAgent 两层体系呢?这里有两个现实的原因:

  • 管理系统一般是一个中央控制的控制软件,而 SubAgent 直接监控一些资源,往往和这些传达管理系统的控制指令的时候,需要提供一些网络传资源分布在同一物理位置。当这些 SubAgent 把状态信息传输到管理系统或者输的功能。
  • 管理系统的消息是有一定规范的,消息的翻译本身是件复杂而枯燥的事情。 一般来说,管理系统会将同一物理分布或者功能类似的 SubAgent 分组成一组,由一个共用的 Agent 加以管理。在这个 Agent 里封装了 1 和 2 的功能。



JMX 和管理系统

JMX 既是 Java 管理系统的一个标准,一个规范,也是一个接口,一个框架。图 2 展示了 JMX 的基本架构。


图 2. JMX 构架



和其它的资源系统一样,JMX 是管理系统和资源之间的一个接口,它定义了管理系统和资源之间交互的标准。javax.management.MBeanServer 实现了 Agent 的功能,以标准的方式给出了管理系统访问 JMX 框架的接口。而 javax.management.MBeans 实现了 SubAgent 的功能,以标准的方式给出了 JMX 框架访问资源的接口。而从类库的层次上看,JMX 包括了核心类库 java.lang.management 和 javax.management 包。java.lang.management 包提供了基本的 VM 监控功能,而 javax.management 包则向用户提供了扩展功能。

JMX 的基本框架

JMX 使用了 Java Bean 模式来传递信息。一般说来,JMX 使用有名的 MBean,其内部包含了数据信息,这些信息可能是:应用程序配置信息、模块信息、系统信息、统计信息等。另外,MBean 也可以设立可读写的属性、直接操作某些函数甚至启动 MBean 可发送的 notification 等。MBean 包括 Standard,MXBean,Dynamic,Model,Open 等几种分类,其中最简单是标准 MBean 和 MXBean,而我们使用得最多的也是这两种。MXBean 主要是 java.lang.management 使用较多,将在下一节中介绍。我们先了解其他一些重要的 MBean 的种类。

标准 MBean

    标准 MBean 是最简单的一类 MBean,与动态 Bean 不同,它并不实现 javax.management 包中的特殊的接口。说它是标准 MBean, 是因为其向外部公开其接口的方法和普通的 Java Bean 相同,是通过 lexical,或者说 coding convention 进行的。下面我们就用一个例子来展现,如何实现一个标准 MBean 来监控某个服务器 ServerImpl 状态的。ServerImpl 代表了用来演示的某个 Server 的实现:

Java代码 复制代码
  1. package standardbeans;   
  2. public class ServerImpl ...{   
  3.     public final long startTime;   
  4.     public ServerImpl() ...{   
  5.         startTime = System.currentTimeMillis();   
  6.     }   
  7. }  
package standardbeans;
public class ServerImpl ...{
    public final long startTime;
    public ServerImpl() ...{
        startTime = System.currentTimeMillis();
    }
}


然后,我们打算使用一个标准 MBean,ServerMonitor 来监控 ServerImpl:

Java代码 复制代码
  1. package standardbeans;   
  2. public class ServerMonitor implements ServerMonitorMBean ...{   
  3.     private final ServerImpl target;   
  4.     public ServerMonitor(ServerImpl target)...{   
  5.         this.target = target;   
  6.     }   
  7.     public long getUpTime()...{   
  8.         return System.currentTimeMillis() - target.startTime;   
  9.     }   
  10. }  
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 规定了标准 MBean 也要实现一个接口,所有向外界公开的方法都要在这个接口中声明。否则,管理系统就不能从中获得相应的信息。此外,该接口的名字也有一定的规范:即在标准 MBean 类名之后加上“MBean”后缀。若 MBean 的类名叫做 MBeansName 的话,对应的接口就要叫做 MBeansNameMBean。

对于管理系统来说,这些在 MBean 中公开的方法,最终会被 JMX 转化成属性(Attribute)、监听(Listener)和调用(Invoke)的概念。如果读者对 Java Bean 有一些了解的话,不难看出,public long getUpTime() 对应了 Bean 中的一个称为“upTime”的只读属性。

下面我们就看一个模拟管理系统的例子:

Java代码 复制代码
  1. package standardbeans;   
  2. import javax.management.MBeanServer;   
  3. import javax.management.MBeanServerFactory;   
  4. import javax.management.ObjectName;   
  5. public class Main ...{   
  6.     private static ObjectName objectName ;   
  7.     private static MBeanServer mBeanServer;   
  8.     public static void main(String[] args) throws Exception...{   
  9.         init();   
  10.         manage();                  
  11.     }   
  12.     private static void init() throws Exception...{   
  13.         ServerImpl serverImpl = new ServerImpl();   
  14.         ServerMonitor serverMonitor = new ServerMonitor(serverImpl);   
  15.         mBeanServer = MBeanServerFactory.createMBeanServer();   
  16.         objectName = new ObjectName("objectName:id=ServerMonitor1");   
  17.         mBeanServer.registerMBean(serverMonitor,objectName);     
  18.     }   
  19.     private static void manage() throws Exception...{   
  20.         Long upTime = (Long) mBeanServer.getAttribute(objectName,   
  21.         "upTime");   
  22.         System.out.println(upTime);   
  23.     }    
  24. }  
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 已经提供了一个默认实现,可以通过

Java代码 复制代码
  1. MBServerFactory.createMBeanServer()  
MBServerFactory.createMBeanServer()

获得。每个资源监控者(MBean)一般都会有名称(ObjectName), 登记在 MBServer 内部的一个 Repository 中。注意,这个 ObjectName 对于每一个 MBServer 必须是唯一的,只能对应于一个 MBean。(读者有兴趣的话,可以试着再给 mBeanServer 注册一个同名的 objectName,看看会怎么样。) 上述例子是在 init() 方法中完成向 MBeanServer 注册工作的。

在管理过程中,管理系统并不与资源或者 SubAgent 直接打交道,也就是说,这里不会直接引用到 MBean。而是通过 MBeanServer 的 getAttribute 方法取得对应 MBean 的属性的。

动态 MBean

但是对于很多已有的 SubAgent 实现,其 Coding Convention 并不符合标准 MBean 的要求。重构所有这些 SubAgent 以符合标准 MBean 标准既费力也不实际。JMX 中给出了动态(Dynamic) MBean 的概念,MBServer 不再依据 Coding Convention 而是直接查询动态 MBean 给出的元数据(meta data)以获得 MBean 的对外接口。

Java代码 复制代码
  1. package dynamicbeans;   
  2.   
  3. import javax.management.*;   
  4. import java.lang.reflect.*;   
  5. public class ServerMonitor implements DynamicMBean ...{   
  6.     
  7.     private final ServerImpl target;       
  8.     private MBeanInfo mBeanInfo;       
  9.            
  10.     public ServerMonitor(ServerImpl target)...{   
  11.         this.target = target;   
  12.     }   
  13.        
  14.     //实现获取被管理的 ServerImpl 的 upTime   
  15.     public long upTime()...{   
  16.         return System.currentTimeMillis() - target.startTime;   
  17.     }   
  18.   
  19.     //javax.management.MBeanServer 会通过查询 getAttribute("Uptime") 获得 "Uptime" 属性值   
  20.     public Object getAttribute(String attribute) throws AttributeNotFoundException,    
  21.         MBeanException, ReflectionException ...{   
  22.         if(attribute.equals("UpTime"))...{   
  23.             return upTime();   
  24.         }   
  25.         return null;   
  26.     }   
  27.        
  28.     //给出 ServerMonitor 的元信息。     
  29.     public MBeanInfo getMBeanInfo() ...{   
  30.         if (mBeanInfo == null) ...{   
  31.             try ...{   
  32.                 Class cls = this.getClass();   
  33.                 //用反射获得 "upTime" 属性的读方法   
  34.                 Method readMethod = cls.getMethod("upTime"new Class[0]);    
  35.                 //用反射获得构造方法   
  36.                 Constructor constructor = cls.getConstructor(new Class[]   
  37.                     ...{ServerImpl.class});   
  38.                 //关于 "upTime" 属性的元信息:名称为 UpTime,只读属性(没有写方法)。   
  39.                 MBeanAttributeInfo upTimeMBeanAttributeInfo = new MBeanAttributeInfo(   
  40.                         "UpTime""The time span since server start",   
  41.                         readMethod, null);   
  42.                 //关于构造函数的元信息   
  43.                 MBeanConstructorInfo mBeanConstructorInfo = new MBeanConstructorInfo(   
  44.                         "Constructor for ServerMonitor", constructor);   
  45.                 //ServerMonitor 的元信息,为了简单起见,在这个例子里,   
  46.                 //没有提供 invocation 以及 listener 方面的元信息    
  47.                 mBeanInfo = new MBeanInfo(cls.getName(),   
  48.                         "Monitor that controls the server",   
  49.                         new MBeanAttributeInfo[] ...{ upTimeMBeanAttributeInfo },   
  50.                         new MBeanConstructorInfo[] ...{ mBeanConstructorInfo },   
  51.                         nullnull);                   
  52.             } catch (Exception e) ...{   
  53.                 throw new Error(e);   
  54.             }   
  55.   
  56.         }   
  57.         return mBeanInfo;   
  58.     }   
  59.   
  60.     public AttributeList getAttributes(String[] arg0) ...{           
  61.         return null;   
  62.     }   
  63.            
  64.     public Object invoke(String arg0, Object[] arg1, String[] arg2)    
  65.         throws MBeanException,    
  66.         ReflectionException ...{           
  67.         return null;   
  68.     }   
  69.   
  70.     public void setAttribute(Attribute arg0) throws AttributeNotFoundException,    
  71.         InvalidAttributeValueException, MBeanException, ReflectionException ...{   
  72.         return;           
  73.     }   
  74.   
  75.     public AttributeList setAttributes(AttributeList arg0) ...{           
  76.         return null;   
  77.     }      
  78. }  
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;
    }
    
    //实现获取被管理的 ServerImpl 的 upTime
    public long upTime()...{
        return System.currentTimeMillis() - target.startTime;
    }

    //javax.management.MBeanServer 会通过查询 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]); 
                //用反射获得构造方法
                Constructor constructor = cls.getConstructor(new Class[]
                    ...{ServerImpl.class});
                //关于 "upTime" 属性的元信息:名称为 UpTime,只读属性(没有写方法)。
                MBeanAttributeInfo upTimeMBeanAttributeInfo = new MBeanAttributeInfo(
                        "UpTime", "The time span since server start",
                        readMethod, null);
                //关于构造函数的元信息
                MBeanConstructorInfo mBeanConstructorInfo = new MBeanConstructorInfo(
                        "Constructor for ServerMonitor", constructor);
                //ServerMonitor 的元信息,为了简单起见,在这个例子里,
                //没有提供 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;
    }   
}


其它动态 MBean

另外还有两类 MBean:Open MBean 和 Model MBean。实际上它们也都是动态 MBean。

Open MBean 与其它动态 MBean 的唯一区别在于,前者对其公开接口的参数和返回值有所限制 —— 只能是基本类型或者 javax.management.openmbean 包内的 ArrayType、CompositeType、TarbularType 等类型。这主要是考虑到管理系统的分布,很可能远端管理系统甚至 MBServer 层都不具有 MBean 接口中特殊的类。

Model Bean

然而,普通的动态 Bean 通常缺乏一些管理系统所需要的支持:比如持久化 MBean 的状态、日志记录、缓存等等。如果让用户去一一实现这些功能确实是件枯燥无聊的工作。为了减轻用户的负担,JMX 提供商都会提供不同的 ModelBean 实现。其中有一个接口是 Java 规范中规定所有厂商必须实现的:javax.management.modelmbean.RequiredModelBean。通过配置 Descriptor 信息,我们可以定制这个 Model Bean, 指定哪些 MBean 状态需要记入日志、如何记录以及是否缓存某些属性、缓存多久等等。这里,我们以 RequiredModelBean 为例讨论 ModelBean。比如,我们先来看一个例子,首先是 server 端:

Java代码 复制代码
  1. package modelmbean;   
  2.   
  3. public class Server ...{   
  4.   
  5.     private long startTime;   
  6.        
  7.     public Server() ...{    }   
  8.        
  9.     public int start()...{   
  10.         startTime = System.currentTimeMillis();   
  11.         return 0;   
  12.     }   
  13.        
  14.     public long getUpTime()...{   
  15.         return System.currentTimeMillis() - startTime;   
  16.     }   
  17. }  
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;
    }
}


然后我们对它的监测如下:

Java代码 复制代码
  1. package modelmbean;   
  2.   
  3. import javax.management.*;   
  4. import javax.management.modelmbean.*;   
  5. public class Main ...{   
  6.        
  7.     public static void main(String[] args) throws Exception...{   
  8.         MBeanServer mBeanServer = MBeanServerFactory.createMBeanServer();   
  9.         RequiredModelMBean serverMBean =   
  10.             (RequiredModelMBean) mBeanServer.instantiate(   
  11.               "javax.management.modelmbean.RequiredModelMBean");           
  12.            
  13.         ObjectName serverMBeanName =   
  14.             new ObjectName("server: id=Server");   
  15.         serverMBean.setModelMBeanInfo(getModelMBeanInfoForServer(serverMBeanName));           
  16.         Server server = new Server();   
  17.         serverMBean.setManagedResource(server, "ObjectReference");   
  18.            
  19.         ObjectInstance registeredServerMBean =   
  20.             mBeanServer.registerMBean((Object) serverMBean, serverMBeanName);   
  21.            
  22.         serverMBean.invoke("start",nullnull);   
  23.            
  24.         Thread.sleep(1000);   
  25.            
  26.         System.out.println(serverMBean.getAttribute("upTime"));   
  27.         Thread.sleep(5000);   
  28.         System.out.println(serverMBean.getAttribute("upTime"));   
  29.     }   
  30.        
  31.     private static ModelMBeanInfo getModelMBeanInfoForServer(ObjectName objectName)    
  32.         throws Exception...{   
  33.         ModelMBeanAttributeInfo[] serverAttributes =   
  34.               new ModelMBeanAttributeInfo[1];   
  35.         Descriptor upTime =   
  36.               new DescriptorSupport(   
  37.                 new String[] ...{   
  38.                   "name=upTime",   
  39.                   "descriptorType=attribute",   
  40.                   "displayName=Server upTime",   
  41.                   "getMethod=getUpTime",                     
  42.                    });   
  43.         serverAttributes[0] =   
  44.               new ModelMBeanAttributeInfo(   
  45.                 "upTime",   
  46.                 "long",   
  47.                 "Server upTime",   
  48.                 true,   
  49.                 false,   
  50.                 false,   
  51.                 upTime);   
  52.            
  53.         ModelMBeanOperationInfo[] serverOperations =   
  54.               new ModelMBeanOperationInfo[2];   
  55.            
  56.         Descriptor getUpTimeDesc =   
  57.               new DescriptorSupport(   
  58.                 new String[] ...{   
  59.                   "name=getUpTime",   
  60.                   "descriptorType=operation",   
  61.                   "class=modelmbean.Server",   
  62.                   "role=operation"                     
  63.                   });   
  64.            
  65.         MBeanParameterInfo[] getUpTimeParms = new MBeanParameterInfo[0];   
  66.         serverOperations[0] = new ModelMBeanOperationInfo("getUpTime",   
  67.                   "get the up time of the server",   
  68.                   getUpTimeParms,   
  69.                   "java.lang.Long",   
  70.                   MBeanOperationInfo.ACTION,   
  71.                   getUpTimeDesc);   
  72.                
  73.         Descriptor startDesc =   
  74.               new DescriptorSupport(   
  75.                 new String[] ...{   
  76.                   "name=start",   
  77.                   "descriptorType=operation",   
  78.                   "class=modelmbean.Server",   
  79.                   "role=operation"  
  80.                   });   
  81.         MBeanParameterInfo[] startParms = new MBeanParameterInfo[0];   
  82.         serverOperations[1] = new ModelMBeanOperationInfo("start",   
  83.                   "start(): start server",   
  84.                   startParms,   
  85.                   "java.lang.Integer",   
  86.                   MBeanOperationInfo.ACTION,   
  87.                   startDesc);   
  88.            
  89.         ModelMBeanInfo serverMMBeanInfo =   
  90.               new ModelMBeanInfoSupport(   
  91.                 "modelmbean.Server",   
  92.                 "ModelMBean for managing an Server",   
  93.                 serverAttributes,   
  94.                 null,   
  95.                 serverOperations,   
  96.                 null);   
  97.            
  98.         //Default strategy for the MBean.   
  99.         Descriptor serverDescription =   
  100.               new DescriptorSupport(   
  101.                 new String[] ...{   
  102.                   ("name=" + objectName),   
  103.                   "descriptorType=mbean",   
  104.                   ("displayName=Server"),   
  105.                   "type=modelmbean.Server",   
  106.                   "log=T",   
  107.                   "logFile=serverMX.log",   
  108.                   "currencyTimeLimit=10" });   
  109.         serverMMBeanInfo.setMBeanDescriptor(serverDescription);   
  110.        return serverMMBeanInfo;   
  111.       }     
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 的过程也是下面几步:

  • 创建一个 MBServer:mBeanServe
  • 获得管理资源用的 MBean:serverBean
  • 给这个 MBean 一个 ObjectName:serverMBeanName
  • 将 serverBean 以 serverMBeanName 注册到 mBeanServer 上去


唯一不同的是,ModelMBean 需要额外两步:

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


第一步用于提供 serverMBean 的元数据,主要包括以下两类

  • 类似于普通的动态 MBean,需要 MBean 的 Attribute、Invocation、Notification 的类型/反射信息,诸如返回类型、参数类型和相关的 get/set 方法等。这里将不再赘述。
  • 关于缓存、持久化以及日志等的策略。后面我们将介绍一些这方面的信息。



第二步指出了 ServerMBean 管理的对象,也就是说,从元数据中得到的 Method 将施加在哪个 Object 上。需要指出的是 setManagedResource(Object o, String type); 中第二个参数是 Object 类型,可以是 "ObjectReference"、"Handle"、"IOR"、"EJBHandle" 或 "RMIReference"。目前 SE 中的实现只支持 "ObjectReference"。笔者认为后面几种类型是为了将来 JMX 管理对象扩展而设定的,可能将来 Model Bean 不仅可以管理 Plain Java Object(POJO),还可能管理 Native Resource, 并给诸如 EJB 和 RMI 对象的管理提供更多的特性。

Model Bean 与普通动态 Bean 区别在于它的元数据类型 ModelMBeanInfo 扩展了前者的 MBeanInfo,使得 ModelMBeanOperationInfo、ModelMBeanConstructor_Info、 ModelMBeanAttributeInfo 和 ModelMBeanNotificationInfo 都有一个额外的元数据:javax.management.Descriptor,它是用来设定 Model Bean 策略的。数据的存储是典型的 "key-value" 键值对。不同的 Model Bean 实现,以及不同的 MBeanFeatureInfo 支持不同的策略特性。下面我们就以 Attribute 为例,看一下 RequiredModelBean 支持的策略。

  • 首先,它最重要的 Descriptor 主要是 name、displayName 和 descriptorType,其中 name 是属性名称。"name" 要与对应 ModelMBeanAttributeInfo 的 name 相同。descriptorType 必须是 "attribute"。
  • 另外,value、default、 legalValues "value" 是用来设定初始值的,"default" 指当不能从 resource 中获得该属性时的默认返回值,"legalValues" 是一组合法的属性数据。它并不用来保证 setAttribute 的数据一致性,而是在 UI 系统,如 JConsole 中提示用户可能的数据输入。
  • 在属性访问的 getMethod, setMethod 方法上,事实上所有对属性的访问都会被 delegate 给同一 MBeanInfo 中特定的 Operation。 getMethod/setMethod 给出了对应的 ModelMBeanOperationInfo 名称。
  • 还有一些额外的属性,比如:persistPolicy, persistPeriod 是代表了持久化策略;currencyTimeLimit, lastUpdatedTimeStamp 缓存策略;iterable 属性是否必须使用 iterate 来访问。默认为否;protocolMap 定义了与第三方系统有关的数据转换的 data model;visibility 定义了与第三方 UI 系统有关的 MBean 如何显示的策略;presentationString 也是定义了与第三方 UI 系统有关的 MBean 如何显示策略,比如 "presentation=server.gif"。


事实上,策略特性有两个层次的作用域:整个 Model Bean 和特定的 MBeanFeature。

Model Bean 的策略描述会被施加到该 Model Bean 的所有 MBeanFeature 上去,除非该 MBeanFeature 重写了这个策略特性。

在上面的例子里,这一个语句:

Java代码 复制代码
  1. serverMMBeanInfo.setMBeanDescriptor(serverDescription);  
serverMMBeanInfo.setMBeanDescriptor(serverDescription);




给整个 serverMBeanInfo 设了一个策略描述 serverDescription,其中用 "currencyTimeLimit=10" 指出属性的缓存时间是 10 秒。所以,在 Main 方法中,两次 serverMBean.getAttribute("upTime");之间的间隔小于 10 秒就会得到同样的缓存值。

如果我们不想让 "upTime" 这个属性被缓存,我们可以在它的策略描述中加入 "currencyTimeLimit=-1":

Java代码 复制代码
  1. Descriptor upTime =    new DescriptorSupport(   
  2.                 new String[] {   
  3.                   "name=upTime",   
  4.                   "descriptorType=attribute",   
  5.                   "displayName=Server upTime",   
  6.                   "getMethod=getUpTime",   
  7.                   "currencyTimeLimit=-1" //不需要缓存   
  8.                    });   
  9.   
  10. Descriptor getUpTimeDesc =   
  11.               new DescriptorSupport(   
  12.                 new String[] {   
  13.                   "name=getUpTime",   </
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值