JMX 介绍

1. 什么是 JMX

         JMX (Java Management Extensions)是一个为应用程序,设备,系统等植入管理功能的框架。

        JMX 规范可以分为三层: 设备层, 代理层, 分布式服务层。 设备层规范定义了编写可由 JMX 管理的资源的标准,即如何写 MBean; 代理曾规范定义了创建代理的规范,封装了 MBean Server;分布式服务层主要定义了对代理层进行操作的管理接口和构件。

        如果一个 Java 对象可以由一个遵循 JMX 规范的管理器应用管理,那么这个Java 对象就可以称为一个可由 JMX 管理的资源。

        要使一个 Java 对象可管理,则必须创建相应的 MBean 对象,并通过这些 MBean 对象管理相应的 Java 对象。当拥有 MBean 类后,需要将其实例化并注册到 MBeanServer 上。

       一共有四种类型的 MBean , 分别是标准类型 MBean, 动态类型 MBean, 开放类型 MBean 和模型类型 MBean。我们在下文将分别进行介绍。

2. JMX API 简单介绍

        本部分对 JMX 中常用的一些类进行简单的介绍。

2.1 MBeanServer

public ObjectInstance createMBean(String className, ObjectName name).

        创建 MBean,并将其注册到 MBeanServer.

public ObjectInstance registerMBean(Object object, ObjectName name).

        将Java对象注册到 MBeanServer。

public Set queryNames(ObjectName name, QueryExp query).

        根据对象名查找注册的 MBean, 返回的 Set 中包含的是查找到的 MBean  对应的 ObjectName。

public Set queryMBeans(ObjectName name, QueryExp query).

        返回的 Set 中包含的是 ObjectInstance 对象。

pubilc Attribute getAttribute(ObjectName name, String attributeName).

        返回指定 name 代表的 MBean 的名为 attributeName 的属性。

public void setAttribute(ObjectName name, Attribute attr).

        设置属性

public invoke(ObjectName name, String methodName, ..., ...).

       执行 指定 MBean 的指定方法。

2.2 MBeanServerFactory

public static MBeanServer createMBeanServer().

        创建 MBeanServer.

2.3 ObjectName

        ObjectName 由两部分组成: domain 和 键/值对。如下面是一个是一个有效的对象名称:

        myDomain:type=Car,color=blue

public ObjectName(String name).

        根据 name 构造ObjectName  对象。

2.4 ObjectInstance

2.5 Attribute

3. 标准 MBean

        标准 MBean 是最简单的 MBean 类型。通过标准 MBean 来管理一个 Java 对象需要以下步骤:

        1. 创建一个接口, 命名规范为: Java 类名 + MBean 后缀。如 Java 类为 Car ,则需要创建 CarMBean 接口。

        2. 修改 Java 类,使它实现创建的接口。如上面提到的 CarMBean。

        3. 创建代理,该代理包含 MBeanServer 实例。

        4. 为 MBean 创建 ObjectName 实例。

        5. 实例化 MBeanServer。

        6. 将 MBean 注册到 MBeanServer。

        下面我们介绍一个标准 MBean 的例子。如我们有一个 Car 类:

package test;

public class Car{
	private String color = "red";
	
	public String getColor(){
		return color;
	}
	public void setColor(String color){
		this.color = color;
	}
	public void drive(){
		System.out.println("Baby you can drive my car.");
	}
}
        那么,第一步我们需要创建 名字为 CarMBean 的接口:

package test;

public interface CarMBean {
	public String getColor();
	public void setColor(String color);
	public void drive();
}

        接下类使 Car 实现 CarMBean:

package test;

public class Car implements CarMBean{
	private String color = "red";
	
	public String getColor(){
		return color;
	}
	public void setColor(String color){
		this.color = color;
	}
	public void drive(){
		System.out.println("Baby you can drive my car.");
	}
}

        然后创建代理:

package test;

import javax.management.Attribute;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectName;

public class StandardAgent {
	private MBeanServer mBeanServer = null;
	public StandardAgent(){
		mBeanServer = MBeanServerFactory.newMBeanServer();
	}
	
	public MBeanServer getMBeanServer(){
		return mBeanServer;
	}
	
	public ObjectName createObjectName(String name){
		ObjectName objectName = null;
		try{
			objectName = new ObjectName(name);
		}catch(Exception e){
		}
		return objectName;
	}
	private void createStandardBean(ObjectName objectName, String managedResourceClassName){
		try{
			mBeanServer.createMBean(managedResourceClassName, objectName);
		}catch(Exception e){}
	}
	
	public static  void main(String[] args){
		StandardAgent agent = new StandardAgent();
		MBeanServer mBeanServer = agent.getMBeanServer();
		String domain = mBeanServer.getDefaultDomain();
		String managedResourceClassName = "test.Car";
		ObjectName objectName = agent.createObjectName(domain + ":type=" + managedResourceClassName);
		System.out.println("objectName: " + objectName);
		agent.createStandardBean(objectName, managedResourceClassName);
		
		try{
			Attribute colorAttribute = new Attribute("Color", "blue");
			mBeanServer.setAttribute(objectName, colorAttribute);
			System.out.println(mBeanServer.getAttribute(objectName, "Color"));
			mBeanServer.invoke(objectName, "drive", null, null);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}

         该类的 main() 方法首先创建 StandardAgent 的一个实例,并获取 MBeanServer。然后创建 ObjectName 实例,并使用 MBeanServer的默认域作为ObjectName 的域。然后通过 CarMBean 实例来管理 Car 对象。

4. 动态 MBean(略)

5. 开放 MBean (略)

6. 模型 MBean

        相对于标准 MBean,模型 MBean 更加灵活。如果我们不能修改已有的 Java 类,那么使用模型 MBean 是不错的选择。不过,模型 MBean 直接变成的难度更大一些。后面我们会介绍到使用 Apache 的 Common Modeler 来简化模型 MBean 过程。

6.1 模型 MBean 的相关类和接口

ModelMBean 接口

        使用模型 MBean,我们不需要像在标准 MBean 中那样定义接口。使用 ModelMBean 接口是不错的选择。

RequiredModelMBean 类

        JMX 的参考实现中的一个 ModelMBean 接口的默认实现类。

ModelMBeanInfo 接口

        编写模型 MBean 的最大挑战是告诉 ModelMBean 对象托管资源的哪些属性和方法可以暴露给代理。ModelMBeanInfo 对象描述了将会暴露给代理的构造函数、属性、操作甚至是监听器。

        创建了 ModelMBeanInfo 对象后,需要将其与 ModelMBean 对象关联。目前有两种方式可以做到这一点:

        1) 传入 ModelMBeanInfo 对象给 RequiredModelMBean 对象的构造函数。

        2) 调用 RequiredModelMBean 对象的 setModelMBeanInfo 方法。

        创建了 ModelMBean 对象后,需要调用 ModelMBean 接口的 setManagedResource() 方法将其与托管资源关联。该方法如下:

         public void setManagedResource(Object managedResource, String managedResourceType) ;

        managedResourceType 的值可以为 ObjectReference、Handle、IOR、EJBHandle 或 RMIReference,但当前只支持 ObjectReference。

ModelMBeanInfoSupport 类

        ModelMBeanInfo 接口的默认实现。该类的构造函数如下:

        public ModelMBeanInfoSupport(String className, String description, ModelMBeanAttributeInfo[] attributes, ModelMBeanConstructorInfo[] constructors, ModelMBeanOperationInfo[] operations, ModelMBeanNotificationInfo[] notifications);

        我们接下来介绍参数中出现的几个类。

ModelMBeanAttributeInfo 类

        模型 MBean 的属性信息。可以通过如下构造函数构造:

        public ModelMBeanAttributeInfo(String name, String type, String description, boolean isReadable, boolean isWritable, boolean isIs, Descriptor descriptor);

ModelMBeanConstructorInfo 类

ModelMBeanOperationInfo 类

        构造函数如下:

        public ModelMBeanOperationInfo(String name, String description, MBeanParameterInfo[] signature, String type, int impact, Descriptor descriptor);

ModelMBeanNotificationInfo 类

6.2 模型 MBean 示例

        我们需要使用模型 MBean 管理如下所示的 Car 对象:

package test;

public class Car implements CarMBean{
	private String color = "red";
	
	public String getColor(){
		return color;
	}
	public void setColor(String color){
		this.color = color;
	}
	public void drive(){
		System.out.println("Baby you can drive my car.");
	}
}

        对于模型 MBean,不需要像使用标准 MBean 那样自己编写接口并使 Car 继承该接口,而只需实例化 RequiredMBean 类即可。如下的 ModelAgent 类用来创建 ModelMbean 用于管理 Car 对象。

package test;

import javax.management.Attribute;
import javax.management.Descriptor;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.modelmbean.DescriptorSupport;
import javax.management.modelmbean.ModelMBean;
import javax.management.modelmbean.ModelMBeanAttributeInfo;
import javax.management.modelmbean.ModelMBeanInfo;
import javax.management.modelmbean.ModelMBeanInfoSupport;
import javax.management.modelmbean.ModelMBeanOperationInfo;
import javax.management.modelmbean.RequiredModelMBean;

public class ModelAgent {
	private String MANAGED_CLASS_NAME = "test.Car";
	private MBeanServer mBeanServer = null;
	
	public ModelAgent(){
		mBeanServer = MBeanServerFactory.createMBeanServer();
	}
	
	public MBeanServer getMBeanServer(){
		return mBeanServer;
	}
	
	private ObjectName createObjectName(String name){
		ObjectName objectName = null;
		try{
			objectName = new ObjectName(name);
		}catch(MalformedObjectNameException e){
			e.printStackTrace();
		}
		return objectName;
	}
	
	private ModelMBean createMBean(ObjectName objectName, String mbeanName){
		ModelMBeanInfo mBeanInfo = createModelMBeanInfo(objectName, mbeanName);
		RequiredModelMBean modelMBean = null;
		try{
			modelMBean = new RequiredModelMBean(mBeanInfo);
		}catch(Exception e){
			e.printStackTrace();
		}
		return modelMBean;
	}
	
	private ModelMBeanInfo createModelMBeanInfo(ObjectName inMbeanObjectName, String inMbeanName){
		ModelMBeanInfo mBeanInfo = null;
		ModelMBeanAttributeInfo[] attributes = new ModelMBeanAttributeInfo[1];
		ModelMBeanOperationInfo[] operations = new ModelMBeanOperationInfo[3];
		try{
			attributes[0] = new ModelMBeanAttributeInfo("Color", "java.lang.String", "the color.", true, true, false, null);
			operations[0] = new ModelMBeanOperationInfo("drive", "the drive method", null, "void", MBeanOperationInfo.ACTION, null);
			operations[1] = new ModelMBeanOperationInfo("getColor", "get color attribute", null, "java.lang.String", MBeanOperationInfo.ACTION, null);
			Descriptor setColorDesc = new DescriptorSupport(new String[]{
					"name=setColor", "descriptorType=operation", "class="+MANAGED_CLASS_NAME, "role=operation"
			});
			MBeanParameterInfo[] setColorParams = new MBeanParameterInfo[]{
				(new MBeanParameterInfo("new color", "java.lang.String", "new Color value"))	
			};
			operations[2] = new ModelMBeanOperationInfo("setColor", "set Color attribute", setColorParams, "void", MBeanOperationInfo.ACTION, setColorDesc);
			mBeanInfo = new ModelMBeanInfoSupport(MANAGED_CLASS_NAME, null, attributes, null, operations, null);
		}catch(Exception e){
			e.printStackTrace();
		}
		return mBeanInfo;
	}
	
	public static void main(String[] args){
		ModelAgent agent = new ModelAgent();
		MBeanServer mBeanServer = agent.getMBeanServer();
		Car car = new Car();
		String domain = mBeanServer.getDefaultDomain();
		ObjectName objectName = agent.createObjectName(domain+":type=MyCar");
		String mBeanName = "myBean";
		ModelMBean modelMBean = agent.createMBean(objectName, mBeanName);
		try{
			//associate the Model MBean with our managed object
			modelMBean.setManagedResource(car, "ObjectReference");
			//register the model MBean to MBeanServer.
			mBeanServer.registerMBean(modelMBean, objectName);
		}catch(Exception e){}
		
		try{
			Attribute attribute = new Attribute("Color", "green");
			mBeanServer.setAttribute(objectName, attribute);
			String color = (String)mBeanServer.getAttribute(objectName, "Color");
			System.out.println("Color:" + color);
			
			attribute = new Attribute("Color", "blueeee");
			mBeanServer.setAttribute(objectName, attribute);
			color = (String)mBeanServer.getAttribute(objectName, "Color");
			System.out.println("Color:" + color);
			
			mBeanServer.invoke(objectName, "drive", null, null);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}


7. Apache 的 Commons Modeler 模型 MBean 库

        使用 Apache 的 Modeler 库创建 Model MBean 的最大帮助是,我们不需要再写复杂的代码来创建 ModelMBeanInfo 对象了。只需要一个 MBean 描述符来对模型 MBean 进行描述,就可以轻松的创建 Model MBean。

1. mbean descriptor (MBean 描述符)

        我们先看一个 MBean 描述符的例子:

<mbean name="StandardServer" 
  className="org.apache.catalina.mbeans.StandardServerMBean" 
  description="Standard Server Component"
  domain="Catalina" 
  group="Server" 
  type="org.apache.catalina.core.StandardServer">

  <attribute name="debug"
    description="The debugging detail level for this component"
    type="int"/>
  <attribute name="managedResource"
    description="The managed resource this MBean is associated with"
    type="java.lang.Object"/>
  <attribute name="port"
    description="TCP port for shutdown message"
    type="int"/>
  <attribute name="shutdown"
    description="Shutdown password"
    type="java.lang.String"/>
  <operation name="store"
    description="Save current state to server.xml"
    impact="ACTION"
    returnType="void">
  </operation>
</mbean>

        上面所示代码生命了一个模型 MBean。这个 MBean 有以下特点:

        1) 它的唯一标识是 StandardServer。

        2) 该 MBean 是 StandardServerMBean 的一个对象。

        3) 它负责管理的对象是 org.apache.catalina.core.StandardServer 类的实例。

        4) domain 属性是 Catalina; group 属性石 Server

        5) 这个 MBean 有四个暴露属性: debug、managedResource、port、shutdown,另外还有一个暴露方法 store().


2. Tomcat Modeler 常用类介绍

Registry 类

ManagedBean 类

        对 Model MBean 的描述。

BaseModelMBean 类

        实现了 ModelMBean 接口。使用这个类就不需要 RequiredModelMBean 类了。另外,该类有一个比较有用的字段 resource。resource 字段标识该模型 MBean 管理的资源。如果在 MBean 描述符的声明中没有指定 className,则默认使用 BaseModelMBean。

3. 使用 Tomcat Model 实现模型 MBean

        我们仍然使用对 Car 类进行管理的例子。

package test;

public class Car{
	private String color = "red";
	
	public Car(){
		System.out.println("Car constructor");
	}

	public String getColor(){
		return color;
	}
	public void setColor(String color){
		this.color = color;
	}
	public void drive(){
		System.out.println("Baby you can drive my car.");
	}
}

我们的 MBean 描述符文件 mbeans-descriptors.xml 文件如下:

<?xml version="1.0"?>
<!DOCTYPE mbeans-descriptors PUBLIC
  "-//Apache Software Foundation//DTD Model MBeans Configuration File" 
  "http://jakarta.apache.org/commons/dtds/mbeans-descriptors.dtd">

<mbeans-descriptors>
  <mbean name="myBean"
    className="javax.management.modelmbean.RequiredModelMBean"
    description="The ModelMBean that manages our Car object"
    type="test.Car">
  
    <attribute name="Color"
      description="The car color"
      type="java.lang.String"/>
    <operation name="drive"
      description="drive method"
      impact="ACTION"
      returnType="void">
      <parameter name="driver" description="the driver parameter" type="java.lang.String"/>
    </operation>
  </mbean>
</mbeans-descriptors>

        代理类 ModelAgent.java 如下所示:

没有更多推荐了,返回首页