`
minghaitang
  • 浏览: 126845 次
社区版块
存档分类
最新评论

JMX MBeans之三Open MBean

阅读更多

JMX MBeans之三Open MBean

  Open MBeans被设计为可以被更大范围的管理程序访问.严格说,你开发standard,dynamic和model MBean可以使用复杂类型。然而,为了让管理程序能够正确得到这些类型的状态,这些类的字节码必须让这些管理程序访问到。结果就是导致管理程序和被管理资源的耦合度很高。折衷的做法,就是要降低被管理的资源的可维护性。Open MBean的产生就是为了去掉这个需求。采用的方法是,Open MBean使用通用的数据类型。
  管理程序和Open MBeans就可以共享和使用数据和方法,而不需要重新编译,重新组配或者动态链接。所以说,Open MBeans提高了管理系统的灵活性和可扩展性。
  Open MBeans当管理程序无法访问agent的java classes的时候,就特别有用。即使管理程序和agent之间的连接不支持java序列化的时候,也是可以访问Open MBeans的。比如说,管理程序不是java开发的。
  Open MBeans必须实现DynamicMBean接口,以对管理程序提供自我描述。与DynamicMBean的不同,就是Open MBean提供了更复杂的metadata数据,和在接口中,只使用了几种预定义的数据类型。
  判断一个MBean是不是open的,可以根据它返回的MBeanInfo对象来判断。Open MBean返回的是OpenMBeanInfo对象,这个类是MBeanInfo的子类。
  可以使用的基本数据类型为:
java.lang.Void
java.lang.Short
java.lang.Boolean
java.lang.Integer
java.lang.Byte
java.lang.Long
java.lang.Character
java.lang.Float
java.lang.String
java.lang.Double
java.math.BigDecimal
java.math.BigInteger
java.util.Date
javax.management.ObjectName
javax.management.openmbean.CompositeData (interface)
javax.management.openmbean.TabularData (interface)
CompositeData接口定义了一个复杂open数据对象的类型,代表了
复合数据结构.
TabularData则代表了List型列表数据.
由于CompositeData和TabularData也都是基本数据类型,所以它们也可以包含其他
CompositeData和TabularData数据,具体任意的复杂性.
CompositeData接口的实现类为CompositeDataSupport
TabularData接口的实现类为TabularDataSupport
 
OpenType抽象类描述:
SimpleType, ArrayType, CompositeType, 和 TabularType
继承了OpenType,可以容纳各种的基本类型数据.
 
Open MBean 元数据类
1. OpenMBeanInfo - 列出所有属性,方法,构造函数和notifications
    OpenMBeanInfoSupport实现了OpenMBeanInfo,并且继承了MBeanInfo
2. OpenMBeanOperationInfo - 描述一个方法
3. OpenMBeanConstructorInfo - 描述一个构造函数
4. OpenMBeanParameterInfo - 描述一个方法参数
5. OpenMBeanAttributeInfo - 描述一个属性

例子:
------------SampleOpenMBean.java------------------
import java.util.*;
import javax.management.*;
import javax.management.openmbean.*;
/**
 * 分数列表Open MBean, 可以被agent进行管理
 */
public class SampleOpenMBean implements DynamicMBean {
 // Open MBean Info
 private OpenMBeanInfoSupport OMBInfo;
 // 被管理的属性
 // 成绩表
 private TabularDataSupport scores;
 // 修改的次数
 private int nbChanges = 0;
 // 此Open MBean类使用的open types 和相关信息
 // 3项:学生名字,科目,分数
 private static String[] itemNames = { "name", "subject", "score" };
 // 各个字段的注释
 private static String[] itemDescriptions = { "name of student", "subject",
   "score" };
 // 数据类型
 private static OpenType[] itemTypes = { SimpleType.STRING,
   SimpleType.STRING, SimpleType.FLOAT };
 // 分数类型
 private static CompositeType scoreType = null;
 // 分数可以根据名字和科目来索引
 private static String[] indexNames = { "name", "subject" };
 private static TabularType scoresType = null;
 // 有效值
 private static String[] legalNames = { "Li", "Wang" };
 private static OpenMBeanParameterInfoSupport nameParamInfo;
 // 科目有效值, 语文,数学,物理
 private static String[] legalSubjects = { "Chinese", "Math", "Physics" };
 private static OpenMBeanParameterInfoSupport subjectParamInfo;
 // 分数有效值的范围
 private static float minScore = 0.0f;
 private static float maxScore = 100.0f;
 private static OpenMBeanParameterInfoSupport scoreParamInfo;
 /**** 静态初始化块 *** */
 static {
  // 初始化 OpenType 实例和ParameterInfo实例
  try {
   // 为分数创建CompositeType实例
   scoreType = new CompositeType("Score", "a score", itemNames,
     itemDescriptions, itemTypes);
   // 为分数表创建TabularType实例
   scoresType = new TabularType("Scores", "all scores", scoreType, // row type
     indexNames);
   // 创建参数信息
   nameParamInfo = new OpenMBeanParameterInfoSupport("name",
     "valid name: " + Arrays.asList(legalNames).toString(),
     SimpleType.STRING, "Li", // 缺省为 Li
     legalNames); // array of legal models
   subjectParamInfo = new OpenMBeanParameterInfoSupport(
     "subject",
     "valid subject: " + Arrays.asList(legalSubjects).toString(),
     SimpleType.STRING, "Chinese", // 缺省为 Chinese
     legalSubjects); // array of legal colors
   scoreParamInfo = new OpenMBeanParameterInfoSupport("score",
     "valid score (From " + minScore + " to " + maxScore + ")",
     SimpleType.FLOAT, null, // 无缺省值
     new Float(minScore), // 最小分数
     new Float(maxScore)); // 最大分数
  } catch (OpenDataException e) {
   // should not happen
  }
 }
 /* *** 构造函数 *** */
 /**
  * Constructs a SampleOpenMBean instance containing an empty scores list
  */
 public SampleOpenMBean() throws OpenDataException {
  buildMBeanInfo();
  // 创建空的分数列表
  scores = new TabularDataSupport(scoresType);
 }
 /**
  * 得到分数列表的克隆对象
  */
 public TabularData getScores() {
  return (TabularData) scores.clone();
 }
 /**
  * 得到分数列表被更改的次数
  */
 public Integer getNbChanges() {
  return new Integer(nbChanges);
 }
 /* *** 操作方法 *** */
 /**
  * 增加一个分数,成功返回Boolean.TRUE if succesful,失败返回Boolean.FALSE.
  */
 public Boolean addScore(CompositeData score) {
  try {
   scores.put(score); //  如何已经存在,则抛出KeyAlreadyExistsException
   nbChanges++;
   return Boolean.TRUE;
  } catch (KeyAlreadyExistsException e) {
   return Boolean.FALSE;
  }
 }
 /**
  * 验证传入的参数是否有效并且返回参数值,如果传入参数为null,则返回缺省值
  */
 protected Object checkParam(OpenMBeanParameterInfo paramInfo, Object param)
   throws OpenDataException {
  Object result;
  if (!paramInfo.isValue(param)) {
   throw new OpenDataException("parameter " + paramInfo.getName()
     + "'s value [" + param + "] is not valid");
  } else if (param == null && paramInfo.hasDefaultValue()) {
   result = paramInfo.getDefaultValue();
  } else {
   result = param;
  }
  return result;
 }
 /**
  * 使用传入的参数创建并且返回一个分数CompositeData实例
  * 如果参数无效,则抛出异常
  */
 public CompositeData buildScore(String name, String subject, Float score)
   throws OpenDataException {
  // 检查参数值是否有效, 如果必要,赋予缺省值,或者抛出异常
  name = (String) checkParam(nameParamInfo, name);
  subject = (String) checkParam(subjectParamInfo, subject);
  score = (Float) checkParam(scoreParamInfo, score);
  Object[] itemValues = { name, subject, score };
  CompositeData result = new CompositeDataSupport(scoreType, itemNames,
    itemValues);
  return result;
 }
 /**
  * 从列表中,移去一个分数
  */
 public void removeScore(CompositeData score) {
  // 如果这个分数存在在列表中,计算这个对象的索引
  Object[] index = scores.calculateIndex(score);
  // 把要删除的分数返回,如果没找到,则什么也不做, 如果删掉,则对更新次数进行加以操作
  CompositeData removed = scores.remove(index);
  if (removed != null) {
   nbChanges++;
  }
 }
 /* *** DynamicMBean接口的方法实现 *** */
 public Object getAttribute(String attribute_name)
   throws AttributeNotFoundException, MBeanException,
   ReflectionException {
  if (attribute_name == null) {
   throw new RuntimeOperationsException(new IllegalArgumentException(
     "Attribute name cannot be null"),
     "Cannot call getAttribute with null attribute name");
  }
  if (attribute_name.equals("Scores")) {
   return getScores();
  }
  if (attribute_name.equals("NbChanges")) {
   return getNbChanges();
  }
  throw new AttributeNotFoundException("Cannot find " + attribute_name
    + " attribute ");
 }
 /**
  *
  */
 public void setAttribute(Attribute attribute)
   throws AttributeNotFoundException, InvalidAttributeValueException,
   MBeanException, ReflectionException {
  throw new AttributeNotFoundException(
    "No attribute can be set in this MBean");
 }
 /**
  *
  */
 public AttributeList getAttributes(String[] attributeNames) {
  if (attributeNames == null) {
   throw new RuntimeOperationsException(new IllegalArgumentException(
     "attributeNames[] cannot be null"),
     "Cannot call getAttributes with null attribute names");
  }
  AttributeList resultList = new AttributeList();
  if (attributeNames.length == 0)
   return resultList;
  for (int i = 0; i < attributeNames.length; i++) {
   try {
    Object value = getAttribute((String) attributeNames[i]);
    resultList.add(new Attribute(attributeNames[i], value));
   } catch (Exception e) {
    e.printStackTrace();
   }
  }
  return (resultList);
 }
 /**
  *
  */
 public AttributeList setAttributes(AttributeList attributes) {
  return new AttributeList(); // always empty
 }
 /**
  *
  */
 public Object invoke(String operationName, Object[] params,
   String[] signature) throws MBeanException, ReflectionException {
  if (operationName == null) {
   throw new RuntimeOperationsException(new IllegalArgumentException(
     "Operation name cannot be null"),
     "Cannot call invoke with null operation name");
  }
  // 如果调用addScore方法
  if (operationName.equals("addScore")) {
   // 检查参数
   if ((params.length != 1) || !(params[0] instanceof CompositeData)) {
    throw new RuntimeOperationsException(
      new IllegalArgumentException(
        "cannot invoke addScore: "
          + "expecting params[i] instanceof CompositeData for i = 0"),
      "Wrong content for array Object[] params to invoke addscore method");
   }
   // 调用addScore方法
   try {
    return addScore((CompositeData) params[0]);
   } catch (Exception e) {
    throw new MBeanException(e, "invoking addScore: "
      + e.getClass().getName() + "caught [" + e.getMessage()
      + "]");
   }
  }
  // 如果是调用removeScore方法
  else if (operationName.equals("removeScore")) {
   // 检查参数
   if ((params.length != 1) || !(params[0] instanceof CompositeData)) {
    throw new RuntimeOperationsException(
      new IllegalArgumentException(
        "cannot invoke removeScore: "
          + "expecting params[i] instanceof CompositeData for i = 0"),
      "Wrong content for array Object[] params to invoke removescore method");
   }
   // 调用removeScore方法
   try {
    removeScore((CompositeData) params[0]);
    return null;
   } catch (Exception e) {
    throw new MBeanException(e, "invoking removeScore: "
      + e.getClass().getName() + "caught [" + e.getMessage()
      + "]");
   }
  }
  // 如果是调用buildScore方法
  else if (operationName.equals("buildScore")) {
   // 检查参数
   if ((params.length != 3) || !(params[0] instanceof String)
     || !(params[1] instanceof String)
     || !(params[2] instanceof Float)) {
    throw new RuntimeOperationsException(
      new IllegalArgumentException(
        "cannot invoke buildScore: "
          + "expecting params[i] instanceof SimpleData for i = 0 to 2"),
      "Wrong content for array Object[] params to invoke buildscore method");
   }
   // 调用buildScore
   try {
    return buildScore((String) params[0], (String) params[1],
      (Float) params[2]);
   } catch (Exception e) {
    throw new MBeanException(e, "invoking buildScore: "
      + e.getClass().getName() + "caught [" + e.getMessage()
      + "]");
   }
  }
  else {
   throw new ReflectionException(new NoSuchMethodException(
     operationName), "Cannot find the operation "
     + operationName);
  }
 } // invoke
 /**
  *
  */
 public MBeanInfo getMBeanInfo() {
  return OMBInfo;
 }
 /* *** Open MBean Info *** */
 /**
  *
  */
 private void buildMBeanInfo() throws OpenDataException {
  OpenMBeanAttributeInfoSupport[] attributes = new OpenMBeanAttributeInfoSupport[2];
  OpenMBeanConstructorInfoSupport[] constructors = new OpenMBeanConstructorInfoSupport[1];
  OpenMBeanOperationInfoSupport[] operations = new OpenMBeanOperationInfoSupport[3];
  MBeanNotificationInfo[] notifications = new MBeanNotificationInfo[0];
  // attribute scores (no default or legal values: not supported for tabular types anyway)
  attributes[0] = new OpenMBeanAttributeInfoSupport("Scores",
    "Score List", scoresType, true, false, false);
  // attribute NbChanges (no default or legal values)
  attributes[1] = new OpenMBeanAttributeInfoSupport("NbChanges",
    "Number of update times.",
    SimpleType.INTEGER, true, false, false);
  // 构造函数
  constructors[0] = new OpenMBeanConstructorInfoSupport(
    "SampleOpenMBean",
    "Constructs a SampleOpenMBean instance containing an empty scores list.",
    new OpenMBeanParameterInfoSupport[0]);
  // addscore方法
  OpenMBeanParameterInfo[] params_add = new OpenMBeanParameterInfoSupport[1];
  params_add[0] = new OpenMBeanParameterInfoSupport("score", "a score",
    scoreType);
  operations[0] = new OpenMBeanOperationInfoSupport(
    "addScore",
    "Adds the score given in parameter to the list of available scores.",
    params_add, SimpleType.BOOLEAN, MBeanOperationInfo.ACTION);
  // removescore方法
  OpenMBeanParameterInfo[] params_remove = params_add;
  operations[1] = new OpenMBeanOperationInfoSupport(
    "removeScore",
    "Removes the score given in parameter to the list of available scores.",
    params_remove, SimpleType.VOID, MBeanOperationInfo.ACTION);
  // buildscore方法
  OpenMBeanParameterInfo[] params_build = new OpenMBeanParameterInfoSupport[3];
  params_build[0] = nameParamInfo;
  params_build[1] = subjectParamInfo;
  params_build[2] = scoreParamInfo;
  operations[2] = new OpenMBeanOperationInfoSupport(
    "buildScore",
    "Builds and returns a CompositeData score instance from the specified parameters.",
    params_build, scoreType, MBeanOperationInfo.INFO);
  // OpenMBeanInfo对象
  OMBInfo = new OpenMBeanInfoSupport(this.getClass().getName(),
    "Sample Open MBean", attributes, constructors, operations,
    notifications);
 }
}
 
 
------------OpenAgent.java------------------

import java.util.Iterator;
import java.util.Set;
import javax.management.*;
import javax.management.openmbean.*;

public class OpenAgent {
    private static MBeanServer server = MBeanServerFactory.createMBeanServer();
    public static void main(String[] args) {
       
 SampleOpenMBean openMBean = null;
 ObjectName openMBeanObjectName = null;
       
 try {
     // 创建MBeanServer
     // 创建和启动一个HTML协议的adaptor
     ObjectInstance html = server.createMBean("com.sun.jdmk.comm.HtmlAdaptorServer", null);
     server.invoke(html.getObjectName(), "start", new Object[0], new String[0]);
     // 实例化一个SampleOpenMBean
     openMBean = new SampleOpenMBean();
       
     // 注册到MBean server上去
     openMBeanObjectName = new ObjectName("TestDomain:className=SampleOpenMBean");
     server.registerMBean(openMBean, openMBeanObjectName);
     //打印这个OpenMBean的信息
     printOpenMBeanInfo(openMBeanObjectName);
     // 创建 score1:  null, null, 10.0f
     CompositeData score1 = openMBean.buildScore(null, null,new Float(10.0f));
    
     // 创建 score2:  "Wang", "Physics", 15.0f
     CompositeData score2 = openMBean.buildScore("Wang", "Physics", new Float(15.0f));
     // 用不合法数据来创建
     try {
      openMBean.buildScore("aaa", "bb", new Float(15.0f));
     } catch (OpenDataException ode) {
      System.err.println("[build score with invalid parameter, Message]: " + ode.getMessage());
     }
     // 把Score1加到TabularData
     System.out.println("[add score1, return]: " + openMBean.addScore(score1) );
     // 把Score2加到TabularData
     System.out.println("[add score2, return]: " + openMBean.addScore(score2) );
     printScores(openMBean.getScores());
    
     // 创建score3,跟score1只是分数不同
     CompositeData score3 = openMBean.buildScore(null, null, new Float(15.0f));
    
     // 试图把score3加到TabularData,将会失败,因为分数不是索引的一部分
     echo("[return]: " + openMBean.addScore(score3) );
     printScores(openMBean.getScores());
     // 去掉一个分数
     echo("[remove score2]");
     openMBean.removeScore(score2);
     printScores(openMBean.getScores());
     echo("[remove score1]");
     // 去掉一个分数
     openMBean.invoke("removeScore", new Object[] {score1}, new String[0]);
     printScores(openMBean.getScores());
 } catch(Exception e) {
     e.printStackTrace();
     return;
 }
 System.out.println("\nNow, you can point your browser to http://localhost:8082/");
 System.out.println("or start your client application to connect to this agent.\n");
    }
   
    public static void printScores(TabularData scores) {
     System.out.println("----value-----");
     Set  set = scores.keySet();
     Iterator it =set.iterator();
     while (it.hasNext()) {
   Object element = (Object) it.next();
   System.out.println("\t" + element);
  }
    }
    /**
     * Displays all OpenMBean information for the specified MBean.
     */
    private static void printOpenMBeanInfo(ObjectName openMBeanObjectName) {
 
        echo("\n>>> Getting the OpenMBeanInfo for MBean:\n\t"+ openMBeanObjectName);
        sleep(1000);
        OpenMBeanInfo info = null;
        try {
            info = (OpenMBeanInfoSupport) server.getMBeanInfo(openMBeanObjectName);
        } catch (Exception e) {
            echo("\t!!! Could not get OpenMBeanInfo object for "+ openMBeanObjectName +" !!!");
            e.printStackTrace();
            return;
        }
        echo("\nCLASSNAME   : "+ info.getClassName());
        echo("\nDESCRIPTION : "+ info.getDescription());
 // Attributes
 //
        echo("\n\n----ATTRIBUTES----\n");
        MBeanAttributeInfo[] attrInfos = info.getAttributes();
        if (attrInfos.length>0) {
     OpenMBeanAttributeInfoSupport attrInfo;
            for(int i=0; i<attrInfos.length; i++) {
         attrInfo = (OpenMBeanAttributeInfoSupport) attrInfos[i];
                echo(" -- ATTRIBUTE NAME : "+ attrInfo.getName() +
                     "\tREAD: "+ attrInfo.isReadable() +
                     "\tWRITE: "+ attrInfo.isWritable());
                echo("    DESCRIPTION    : "+ attrInfo.getDescription());
                echo("    JAVA TYPE      : "+ attrInfo.getType());
                echo("    OPEN TYPE      : "+ attrInfo.getOpenType().getClass().getName());
                echo("    DEFAULT VALUE  : "+ attrInfo.getDefaultValue());
                echo("    LEGAL VALUES   : "+ attrInfo.getLegalValues());
                echo("    MIN VALUE      : "+ attrInfo.getMinValue());
                echo("    MAX VALUE      : "+ attrInfo.getMaxValue());
  echo("");
            }
        } else echo(" ** No attributes **\n");
 // Constructors
 //
        echo("\n\n----CONSTRUCTORS----\n");
        MBeanConstructorInfo[] constrInfos =  info.getConstructors();
        if (constrInfos.length>0) {
     OpenMBeanConstructorInfoSupport constrInfo;
     for(int i=0; i<constrInfos.length; i++) {
         constrInfo = (OpenMBeanConstructorInfoSupport) constrInfos[i];
  echo(" -- CONSTRUCTOR NAME : "+ constrInfo.getName());
  echo("    DESCRIPTION      : "+ constrInfo.getDescription());
  MBeanParameterInfo[] paramInfos = constrInfo.getSignature();
  echo("    PARAMETERS       : "+ paramInfos.length +" parameter"+ ( paramInfos.length>1 ? "s\n" : "" ));
  if (paramInfos.length>0) {
      OpenMBeanParameterInfoSupport paramInfo;
      for(int j=0; j<paramInfos.length; j++) {
   paramInfo = (OpenMBeanParameterInfoSupport) paramInfos[j];
   echo("    ."+(j+1)+". PARAMETER NAME : "+ paramInfo.getName());
   echo("        DESCRIPTION    : "+ paramInfo.getDescription());
   echo("        JAVA TYPE      : "+ paramInfo.getType());
   echo("        OPEN TYPE      : "+ paramInfo.getOpenType().getClass().getName());
   echo("        DEFAULT VALUE  : "+ paramInfo.getDefaultValue());
   echo("        LEGAL VALUES   : "+ paramInfo.getLegalValues());
   echo("        MIN VALUE      : "+ paramInfo.getMinValue());
   echo("        MAX VALUE      : "+ paramInfo.getMaxValue());
   echo("");
      }
  }
  echo("");
     }
        } else echo(" ** No constructors **\n");
 // Operations
 //
        echo("\n\n----OPERATIONS----\n");
        MBeanOperationInfo[] opInfos =  info.getOperations();
        if (opInfos.length>0) {
     OpenMBeanOperationInfoSupport opInfo;
            for(int i=0; i<opInfos.length; i++) {
  opInfo = (OpenMBeanOperationInfoSupport) opInfos[i];
                echo(" -- OPERATION NAME   : "+ opInfo.getName());
                echo("    DESCRIPTION      : "+ opInfo.getDescription());
                echo("    RETURN JAVA TYPE : "+ opInfo.getReturnType());
                echo("    RETURN OPEN TYPE : "+ opInfo.getReturnOpenType().getClass().getName());
  MBeanParameterInfo[] paramInfos = opInfo.getSignature();
                echo("    PARAMETERS       : "+ paramInfos.length +" parameter"+ ( paramInfos.length>1 ? "s\n" : "" ));
  if (paramInfos.length>0) {
      OpenMBeanParameterInfoSupport paramInfo;
      for(int j=0; j<paramInfos.length; j++) {
   paramInfo = (OpenMBeanParameterInfoSupport) paramInfos[j];
   echo("    ."+(j+1)+". PARAMETER NAME : "+ paramInfo.getName());
   echo("        DESCRIPTION    : "+ paramInfo.getDescription());
   echo("        JAVA TYPE      : "+ paramInfo.getType());
   echo("        OPEN TYPE      : "+ paramInfo.getOpenType().getClass().getName());
   echo("        DEFAULT VALUE  : "+ paramInfo.getDefaultValue());
   echo("        LEGAL VALUES   : "+ paramInfo.getLegalValues());
   echo("        MIN VALUE      : "+ paramInfo.getMinValue());
   echo("        MAX VALUE      : "+ paramInfo.getMaxValue());
   echo("");
      }
  }
  echo("");
            }
        } else echo(" ** No operations **\n");
 // Notifications
 //
        echo("\n\n----NOTIFICATIONS----\n");
        MBeanNotificationInfo[] notifInfos = info.getNotifications();
        if (notifInfos.length>0) {
            for(int i=0; i<notifInfos.length; i++) {
                echo(" -- NOTIFICATION NAME : "+ notifInfos[i].getName());
                echo("    DESCRIPTION       : "+ notifInfos[i].getDescription());
  echo("");
            }
        } else echo(" ** No notifications **\n");
    }

    private static void echo(String msg) {
        System.out.println(msg);
    }
 
    private static void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            return;
        }
    }
}

分享到:
评论
2 楼 cherishlive 2013-04-01  
请问Standard MBean如何支持复杂类型,可否大概的讲下,不胜感激。
1 楼 nihongye 2012-08-08  

相关推荐

Global site tag (gtag.js) - Google Analytics