隨筆 - 12, 文章 - 0, 評論 - 22, 引用 - 0
          數據加載中……

          JMX分析3-MXBean及OpenMBean

                 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接口

           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的實現類
           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基本類型)
           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
           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端
           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中的方法前后,對參數或者返回值進行轉化。
           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的實現。

          參考:
          http://tuhaitao.iteye.com/blog/807398 (JMX學習筆記(三)-MXBean )

          posted on 2012-11-27 00:39 heavensay 閱讀(3789) 評論(0)  編輯  收藏 所屬分類: JMX


          只有注冊用戶登錄后才能發表評論。


          網站導航:
          博客園   IT新聞   Chat2DB   C++博客   博問  
           
          主站蜘蛛池模板: 垣曲县| 黔江区| 芦溪县| 泾源县| 东明县| 惠安县| 罗定市| 昌宁县| 绥中县| 留坝县| 哈巴河县| 定陶县| 岳阳县| 谢通门县| 西贡区| 洛川县| 绥江县| 竹溪县| 东莞市| 绥芬河市| 乌鲁木齐县| 若尔盖县| 万载县| 常州市| 手游| 宣武区| 汉川市| 南和县| 合江县| 丹东市| 永昌县| 姜堰市| 习水县| 富裕县| 麻江县| 酒泉市| 同心县| 科技| 海城市| 昆山市| 郑州市|