JMX 分析3-MXBean及OpenMBean

http://www.blogjava.net/heavensay/archive/2012/11/27/388202.html

       MXBean跟标准MBean很像,标准MBean需要实现XXXXMBean这样命名的接口,而MXBean则需要实现XXXXMXBean这样命名的接口,也可以在接口上使用注解@MXBean,而不用强制使用XXXMXBean这样的命名格式。但是MXBean有点在于它可以供任何的client,包括remote client访问相关属性和执行相关操作。并且client不需要具有MXBean类(e.g. 在JConsole中,MBean类型也可以供remote client访问,基本类型是可以展示的,但是一旦有复杂类型,那就不能显示了)。为了满足这种机制,JMX提供了一套Open type-Open value用于双方交互。以使耦合度减少。VM的很多属性都是通过MXBean的形式提供的。
例子:
代码:ZooMXBean,MXBean接口


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->  1  package test.jmx.mxbean.simple;
 2 
 3  public  interface ZooMXBean {
 4     
 5      public Tiger getTiger();
 6     
 7      public  void addTiger(Tiger tiger);
 8     
 9      public String getZooName();
10     
11      public  int getTigerCount();
12 }
13 

代码:ZooImpl,MXBean的实现类

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->  1  package test.jmx.mxbean.simple;
 2 
 3  import java.util.ArrayList;
 4  import java.util.List;
 5 
 6  public  class ZooImpl  implements ZooMXBean {
 7 
 8      private String zooName = " China zoo";
 9      private  static List<Tiger> list;
10      static {
11          // 初始化一只Tiger
12          Tiger tiger =  new Tiger(" the first tiger");
13         list =  new ArrayList<Tiger>();
14         list.add(tiger);
15     }
16      public  void addTiger(Tiger tiger) {
17         list.add(tiger);
18     }
19 
20      public Tiger getTiger() {
21          return list.get(0);
22     }
23 
24      public  int getTigerCount(){
25          return list.size();
26     }
27     
28      public String getZooName() {
29          return zooName;
30     }
31     
32      public String[] getAnimalNames(){
33          return  new String[]{"bird","tiger","mouse"};
34     };
35 }
36 

代码:Tiger,复杂的类型(不同于java基本类型)

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->  1  package test.jmx.mxbean.simple;
 2 
 3  import java.beans.ConstructorProperties;
 4 
 5 
 6  public  class Tiger {
 7     
 8      private String name;
 9     @ConstructorProperties({})
10      public Tiger(){
11          this.name = "the default constructor";
12     }
13     
14     @ConstructorProperties({"name"})
15      public Tiger(String name){
16          this.name = name;
17     }
18     
19      public String getName(){
20          return name;
21     }
22     
23      public String roar(){
24          return "@¥%%……";
25     }
26     
27      public  void setName(String name){
28          this.name=name;
29     }
30      public String[] getFoodNames(){
31          return  new String[]{"rabbit","sheep","pig"};
32     }
33 }
34 

代码:Server

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->  1  package test.jmx.mxbean.simple;
 2 
 3  import java.lang.management.ManagementFactory;
 4  import java.rmi.registry.LocateRegistry;
 5 
 6  import javax.management.MBeanServer;
 7  import javax.management.ObjectName;
 8  import javax.management.remote.JMXConnectorServer;
 9  import javax.management.remote.JMXConnectorServerFactory;
10  import javax.management.remote.JMXServiceURL;
11 
12  public  class Server {
13      public  static  void main(String args[])  throws Exception{
14         
15  //         MBeanServer mbs = MBeanServerFactory.createMBeanServer();
16          MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
17         LocateRegistry.createRegistry(9999);
18         JMXServiceURL url =  new JMXServiceURL(
19                 "service:jmx:rmi:///jndi/rmi://localhost:9999/server");
20         JMXConnectorServer cs = JMXConnectorServerFactory
21                 .newJMXConnectorServer(url,  null, mbs);
22         
23         ZooMXBean mxbean =  new ZooImpl();
24         ObjectName name =  new ObjectName("ZooMXBean:type=MXBean");
25          // 注册ZooOpenMBean这个OpenMBean
26          mbs.registerMBean(mxbean, name);
27          // 开起RMI服务
28          cs.start();
29         
30         System.out.println(" the mxbean server is start ");
31     }
32 }
33 

代码:Client端

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->  1 
 2  package test.jmx.mxbean.simple;
 3 
 4 
 5 
 6  import javax.management.MBeanServerConnection;
 7  import javax.management.ObjectName;
 8  import javax.management.openmbean.ArrayType;
 9  import javax.management.openmbean.CompositeData;
10  import javax.management.openmbean.CompositeDataSupport;
11  import javax.management.openmbean.CompositeType;
12  import javax.management.openmbean.OpenType;
13  import javax.management.openmbean.SimpleType;
14  import javax.management.remote.JMXConnector;
15  import javax.management.remote.JMXConnectorFactory;
16  import javax.management.remote.JMXServiceURL;
17 
18  public  class Client {
19     
20      public  static  void main(String[] args)  throws Exception{
21 
22          // 构造一个Rmi-Connector
23          JMXServiceURL url =  new JMXServiceURL(
24                 "service:jmx:rmi:///jndi/rmi://localhost:9999/server");
25         JMXConnector jmxc = JMXConnectorFactory.connect(url,  null);
26         MBeanServerConnection msc = jmxc.getMBeanServerConnection();
27         
28         ObjectName name =  new ObjectName("ZooMXBean:type=MXBean");
29         
30         Object tiger = msc.getAttribute(name, "Tiger");
31          if(tiger  instanceof CompositeData){
32             System.out.println("返回的Tiger的类型为CompositeData");
33             CompositeData data = (CompositeData)tiger;
34             String nm = (String)(data.get("name"));
35             String[] foods = (String[])(data.get("foodNames"));
36             System.out.println(" the tiger's name is :"+nm);
37             System.out.println(" the tiger's foods is :"+foods);
38         }
39         
40         Integer count1 = (Integer)msc.getAttribute(name, "TigerCount");
41         System.out.println(" the amount of tiger is:"+count1);
42         
43          // 构造一个CompositeData代表Tiger实例,用于addTiger(Tiger)的参数
44          CompositeType ct2 =  new CompositeType("test.jmx.mxbean.Tiger", " tiger---",
45                  new String[]{"name","foodNames"},
46                  new String[]{"-name-","-foods-"}, 
47                  new OpenType[]{SimpleType.STRING, new ArrayType(1,SimpleType.STRING)});
48         
49         CompositeData ct2V =  new CompositeDataSupport(ct2,
50                  new String[]{"name","foodNames"},
51                     new Object[]{"the second tiger", new String[]{"food1","food2","food3"}}); 
52         
53         Object returnValue = msc.invoke(name, "addTiger", 
54                  new Object[]{ct2V},
55                  new String[]{CompositeData. class.getName()});
56          // 得到服务端Tiger的数量,新增了以后,应该是2只
57          Integer count2 = (Integer)msc.getAttribute(name, "TigerCount");
58         System.out.println(" after invoke addTiger( ),the amount of tiger is:"+count2);
59     }
60 }
61 
      上面例子中,我们自定义了ZooMXBean就是MXBean接口,ZooImpl是其实现类;Tiger为自定义的一个Java类;Server为MBeanServer所在的服务端,可以使用JDK自带的jconsole查看MXBean属性;Client端,主要是验证Tiger是如何转化成Open Type并在Server-Clinet两端操作的。
我们可以通过jconsole查看这个注册的MXBean。

图:ZooMXBean属性


图:Tiger属性


      Jconsole控制台就是JMX兼容的监视工具。它使用Java虚拟机的JMX机制来提供运行在Java平台的应用程序的各种信息。在上图中我们可以看出属性中Tiger值是CompositeDataSupport。为什么我们在ZooXMBean接口中定义的getTiger()方法,也即属性Tiger的值为Tiger类的实例。但是jconsole平台显示的确是一个CompositeDataSupport呢。首先在jconsole这边是没有Tiger这个类的,即jconsole这端是不可能实例化出一个Tiger类型的实例的。但是CompositeDataSupport(父类:CompositeData)在JMX机制中是属于Open Data。说到Open Data就得说下JMX 中的OpenMBean了,在OpenMBean中为了实现但新增一个'MBean',的时候Manager Application可以再运行时能发现这个新增'MBean',管理员能知道这个'MBean'的意思,和如何操作;并且不需要重新编译。为了实现上述功能,JMX中有一套Open Type-Open Value集合。Manager Application与Agent之间的通信需要使用这套类型。正式应该在Manager Application中也知道CompoisteData的结构,故能从中取得相应的数据,而不需要知道Tiger类。

表格1:Open type和Java Type对应关系

Java Type

Open Type

Open Value

java.lang.Void

SimpleType.Void

\

java.lang.Boolean

SimpleType.Boolean

java.lang.Boolean

java.lang.Character

SimpleType.Character

java.lang.Character

java.lang.Byte

SimpleType.Byte

java.lang.Byte

java.lang.Short

SimpleType.Short

java.lang.Short

java.lang.Integer

SimpleType.Integer

java.lang.Integer

java.lang.Long

SimpleType.Long

java.lang.Long

java.lang.Float

SimpleType.Float

java.lang.Float

java.lang.Double

SimpleType.Double

java.lang.Double

java.lang.String

SimpleType.String

java.lang.String

java.math.BigDecimal

SimpleType.BigDecimal

java.math.BigDecimal

java.math.BigInteger

SimpleType.BigInteger

java.math.BigInteger

java.util.Date

SimpleType.Date

java.util.Date

javax.management.ObjectName

javax.management.ObjectName

javax.management.ObjectName

javax.management.openmbean.CompositeType

javax.management.openmbean.CompositeType

CompositeData

javax.management.openmbean.TabularType

javax.management.openmbean.TabularType

TabularData

 

javax.management.openmbean.ArrayType

以上Open value的数组形式,任意维度


Clinet与Server交互的流程:
    1. Server端注册一个MXBean的时候,JMX内部会通过MXBeanMappingFactory.mappingForType(Type t, MXBeanMappingFactory f)方法建立起Java type 到Open Type的映射关系。
    2. client客户端执行getAttribute(...)或者invoke(...)操作的时候。需要传递一个Open Type的参数。想ZooMXBean.addTiger(Tiger)需要一个参数,但是client端,是没有Tiger类的,这时候就需要构造一个CompositeType类型的值CompositeData传递给Server。
    3. Server收到传递过来的Open Type参数,通过MXBeanMapping.fromOpenValue(Object openValue)把Open Type类型的参数Open Value转化到Java Type类型的Java Value实例(i.e. 如何参数为代表Tiger的CompositeData,那么MXBeanMapping就会通过这个CompositeData,构造出一个真正的Tiger实例)。
    4.  Server端调用MXBean方法,得到一个Java Type的返回值。如果有返回值,那么就会通过MXBeanMapping.toOpenValue(Object javaValue)把Java Value转换成Open Value。传递成client。
    5. server-client端对于Open-Type的机制都是知道的。于是client就可以在得到的Open Value中得到想要的数据(不需要server端自定义类的字节码,如Tiger)。


  • 相关的类介绍:

MXBeanMapping、MXBeanMappingFactory、DefaultMXBeanMappingFactory
图:MXBeanMappingFactory、MXBeanMapping结构



       MXBeanMapping用于Open Type-Java Type的映射,使它们可以相互转化。MXBeanMappingFactory.mappingForType(Type t, MXBeanMappingFactory f)创建MXBeanMapping。DefaultMXBeanMappingFactory是MXBeanMappingFactory实现类,而MXBeanMapping的实现类是作为DefaultMXBeanMappingFactory内部类。这些类是在JDK7中的sun包中的。不同的JDK可能实现不一样,类名也可能不存在。 

  ConvertingMethod
主要用于在执行MXBean中的方法前后,对参数或者返回值进行转化。

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->  1  // MBserServer对MXBean的操作,最终都是执行MXBean接口里面的方法,而ConvertingMethod就是对MXBean里面的方法,进行包装。
   //把调用者的Open Type参数,转化成Java Type;并且接口中方法的Java Type的返回值转换成Open Type返回给调用者

 2  ConvertingMethod:
 3  // 参数m其实就是MXBean接口中定义的方法,也就是需要MBeanServer管理的属性和操作。这个方法用于对m进行相关的包装、转换。m中的参数、返回值都跟Open Type建立映射关系。
   // 通过源码发现,MXBean在被注册的时候,会调用此方法。既MXBean中自定义的属性、参数类型就是在这里更Open Type建立映射关系的
 4       static ConvertingMethod from(Method m) {
 5          try {
 6              return  new ConvertingMethod(m);
 7         }  catch (OpenDataException ode) {
 8              final String msg = "Method " + m.getDeclaringClass().getName() +
 9                 "." + m.getName() + " has parameter or return type that " +
10                 "cannot be translated into an open type";
11              throw  new IllegalArgumentException(msg, ode);
12         }
13     }
14 
15      private ConvertingMethod(Method m)  throws OpenDataException {
16          this.method = m;
17         MXBeanMappingFactory mappingFactory = MXBeanMappingFactory.DEFAULT;
18  // 把m方法的返回值类型映射到Open Type,得到映射关系
19          returnMapping =                mappingFactory.mappingForType(m.getGenericReturnType(), mappingFactory);
20  // 得到m里面的所有参数类型
21          Type[] params = m.getGenericParameterTypes();
22         paramMappings =  new MXBeanMapping[params.length];
23          boolean identity =  true;
24          for ( int i = 0; i < params.length; i++) {
25  // 把m的参数类型也映射到Open Type,得到映射关系
26              paramMappings[i] = mappingFactory.mappingForType(params[i], mappingFactory);
27             identity &= DefaultMXBeanMappingFactory.isIdentity(paramMappings[i]);
28         }
29         paramConversionIsIdentity = identity;
30     }
31 
32  // 通过MBeanServer来取MXBean的属性或执行操作,都会通过这个方法,然后到真正的Source Object执行相应的方法
33       private Object invokeWithOpenReturn(Object obj, Object[] params)
34              throws MBeanException, IllegalAccessException,
35                    InvocationTargetException {
36          final Object[] javaParams;
37          try {
38  // 把Open Type类型参数的值转换到Java Type类型的值
39              javaParams = fromOpenParameters(params);
40         }  catch (InvalidObjectException e) {
41              //  probably can't happen
42               final String msg = methodName() + ": cannot convert parameters " +
43                 "from open values: " + e;
44              throw  new MBeanException(e, msg);
45         }
46  // 通过Source Object执行真正MXBean实例的方法
47           final Object javaReturn = method.invoke(obj, javaParams);
48          try {
49  // 把需要返回给调用者的Java Type返回值,转换成Open Type的值。
50               return returnMapping.toOpenValue(javaReturn);
51         }  catch (OpenDataException e) {
52              //  probably can't happen
53               final String msg = methodName() + ": cannot convert return " +
54                 "value to open value: " + e;
55              throw  new MBeanException(e, msg);
56         }
57     }
58 
59      final Object[] fromOpenParameters(Object[] params)
60              throws InvalidObjectException {
61          if (paramConversionIsIdentity || params ==  null)
62              return params;
63          final Object[] jparams =  new Object[params.length];
64          for ( int i = 0; i < params.length; i++)
65  // 通过Java Type - Open Type映射关系,实现类型转换
66              jparams[i] = paramMappings[i].fromOpenValue(params[i]);
67          return jparams;
68     }
69 


总结:
JMX中对于MXBean的实现中可以看出,主要是定义了一套Open Type,使client端不需要知道Server端MXBean里面相关属性类型的情况下,能得到需要的数据,使程序更具更加灵活、两端耦合段更低。为了得到这种便利性,我们自定义的MXBean和里面相关的自定义类型都需要按照一定规范来实现。其实JMX中的OpenMBean就是用这套Open Types使MBean具有"Open"特性的,具体可以参操MXBean的实现
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JMX(Java Management Extensions)是Java平台的一个管理和监控API,可以让开发人员开发Mbean(Managed Bean)来管理和监控Java应用程序。Mbean是一种Java对象,通过JMX可以公开其属性和方法,以便对其进行管理和监控。 下面是一个简单的示例,演示如何使用JMX开发一个Mbean: 1. 定义一个实现了DynamicMBean接口的类,该类表示一个Mbean: ```java public class SimpleMBean implements DynamicMBean { private String name; public SimpleMBean(String name) { this.name = name; } @Override public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException { if (attribute.equals("Name")) { return name; } else { throw new AttributeNotFoundException(attribute); } } @Override public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException { throw new AttributeNotFoundException(attribute.getName()); } @Override public AttributeList getAttributes(String[] attributes) { AttributeList result = new AttributeList(); for (String attr : attributes) { try { result.add(new Attribute(attr, getAttribute(attr))); } catch (Exception ex) { // ignore } } return result; } @Override public AttributeList setAttributes(AttributeList attributes) { return new AttributeList(); } @Override public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException { throw new ReflectionException(new NoSuchMethodException(actionName)); } @Override public MBeanInfo getMBeanInfo() { MBeanAttributeInfo[] attrs = new MBeanAttributeInfo[] { new MBeanAttributeInfo("Name", "java.lang.String", "name", true, false, false) }; MBeanConstructorInfo[] ctors = new MBeanConstructorInfo[] { new MBeanConstructorInfo("SimpleMBean()", "Default constructor", new MBeanParameterInfo[0]) }; return new MBeanInfo(getClass().getName(), "SimpleMBean", attrs, ctors, null, null); } } ``` 2. 创建一个MBeanServer对象,并将Mbean注册到MBeanServer中: ```java MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); ObjectName name = new ObjectName("com.example:type=SimpleMBean"); SimpleMBean mbean = new SimpleMBean("hello"); mbs.registerMBean(mbean, name); ``` 3. 使用JConsole或其他JMX客户端连接到MBeanServer,可以查看和修改Mbean的属性。 这是一个非常简单的示例,实际上,Mbean可以包含更复杂的逻辑和更多的属性。Mbean也可以使用注解来简化Mbean的开发和管理。JMX是一个强大的工具,可以帮助开发人员监控和管理Java应用程序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值