MBean是被管理的Java对象,类似于JavaBean。它遵循Jmx规范中的设计模式。一个MBean能代表一个需要被管理的设备,应用程序或其他资源。MBeans暴露了管理接口:一组可读,可写属性和调用操作。管理接口在整个MBean实例生命周期总不会改变。当定义的事件发生时,MBean可以输出通知。
JMX规范定义了四种MBean类型:standard MBeans,dynamic MBean,open MBean和Model MBean。
上例中的两个属性,Name是可读的,cachesize是可读、可写的。get和set方法允许被管理的application访问和变更属性值。就像JMX规范中,getter允许manager取读属性值。setter允许manager写新的值到属性中。
1)编译 javac com/example
2)启动 java com.example.mbeans.Main
每个notification都有源,通知的源就是输出notification的MBean的对象名称。并且每个notification都有序列号,当顺序至关重要且notification以错误顺序处理时有很大危险,此号用来从同一个源来的Notification排序。
MXBeans背后的核心理念是类型诸如java.lang.manangement.MemoryUsage,它将在MXBean接口中被引用。java.lang.manangement.MemoryMXBean被映射成一组标准类型,被称为open type(在javax.management.openmbean中定义)。映射规则可参见MXBean规范,但是简单类型如int或string不会改变,然而复杂类型诸如MemoryUsage被 映射成标准类型CompositeDataSupport。
JMX规范定义了四种MBean类型:standard MBeans,dynamic MBean,open MBean和Model MBean。
standard MBeans
standard MBean通过Java interface定义和一个实现此interface的类。接口中定义的每个方法要么是属性要么是MBean的操作。默认每个方法定义了一个操作。属性和操作是遵循特定设计模式的简单方法。standard MBean由MBean interface和实现此接口的class(提供instrumented resource的功能)组成。MBean interface
下例是一个基本的MBean接口package com.example.mbeans;
public interface HelloMBean {
public void sayHello();
public int add(int x, int y);
public String getName();
public int getCacheSize();
public void setCacheSize(int size);
}
根据约定,MBean接口的名称为类名+MBean。根据JMX规范,MBean接口由已命名的、可读写的属性组成,且已命名的类型操作可以被应用程序(被MBean管理的)调用。上例中声明了两个操作add()和sayHello()。
上例中的两个属性,Name是可读的,cachesize是可读、可写的。get和set方法允许被管理的application访问和变更属性值。就像JMX规范中,getter允许manager取读属性值。setter允许manager写新的值到属性中。
MBean Implementation
package com.example.mbeans;
public class Hello implements HelloMBean {
public void sayHello() {
System.out.println("hello, world");
}
public int add(int x, int y) {
return x + y;
}
public String getName() {
return this.name;
}
public int getCacheSize() {
return this.cacheSize;
}
public synchronized void setCacheSize(int size) {
this.cacheSize = size;
System.out.println("Cache size now " + this.cacheSize);
}
private final String name = "Reginald";
private int cacheSize = DEFAULT_CACHE_SIZE;
private static final int DEFAULT_CACHE_SIZE = 200;
}
Java类Hello提供了接口HelloMBean中操作和属性的定义。
Managing a Resource
一旦resource被MBean装配,resource的管理被JMX agent完成。JMX agent的一个核心是MBean server,它是一个被管理的对象server,MBeans在此server中注册。JMX agent也包括一组服务来管理MBeans。package com.example.mbeans;
import java.lang.management.*;
import javax.management.*;
public class Main {
public static void main(String[] args) throws Exception {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("com.example.mbeans:type=Hello");
Hello mbean = new Hello();
mbs.registerMBean(mbean, name);
System.out.println("Waiting forever...");
Thread.sleep(Long.MAX_VALUE);
}
}
如果没有MBean server已经运行在平台上,getPlatformMBeanServer()方法会通过MBeanServerFactory.createMBeanServer()方法自动创建一个。每一个JMX MBean必须有一个object name,它是JMX类ObjectName的实例,且必须遵守JMX规范定义的语法:由domain和一组key-properties组成。在上例中,domain是"com.example.mbeans",key-property是对象的类型是Hello。
HelloMBean在MBeanServer中注册后,类Main会等待Hello上的管理操作。
Running the Standard MBean Example
Java平台有management和moniter console,名为Jconsole,用来与MBean交互。运行上例的步骤:1)编译 javac com/example
2)启动 java com.example.mbeans.Main
3)启动Jconsole,从Jconsole中可以看到MBean。
sending Notifications
MBean可以生成notification,例如可以发送状态变更、被探测事件或一个问题的通知。对MBean来说,生成通知,必须实现NotificationBroadcaster或NotificationEmitter接口。剩下来需要做的事情就是构造javax.management.Notification实例或它的子类AttributeChangedNotification,传递给NotificationBroadcasterSupport。每个notification都有源,通知的源就是输出notification的MBean的对象名称。并且每个notification都有序列号,当顺序至关重要且notification以错误顺序处理时有很大危险,此号用来从同一个源来的Notification排序。
NotificationBroadcaster
package com.example.mbeans;
import javax.management.*;
public class Hello
extends NotificationBroadcasterSupport implements HelloMBean {
public void sayHello() {
System.out.println("hello, world");
}
public int add(int x, int y) {
return x + y;
}
public String getName() {
return this.name;
}
public int getCacheSize() {
return this.cacheSize;
}
public synchronized void setCacheSize(int size) {
int oldSize = this.cacheSize;
this.cacheSize = size;
System.out.println("Cache size now " + this.cacheSize);
Notification n =
new AttributeChangeNotification(this,
sequenceNumber++,
System.currentTimeMillis(),
"CacheSize changed",
"CacheSize",
"int",
oldSize,
this.cacheSize);
sendNotification(n);
}
@Override
public MBeanNotificationInfo[] getNotificationInfo() {
String[] types = new String[] {
AttributeChangeNotification.ATTRIBUTE_CHANGE
};
String name = AttributeChangeNotification.class.getName();
String description = "An attribute of this MBean has changed";
MBeanNotificationInfo info =
new MBeanNotificationInfo(types, name, description);
return new MBeanNotificationInfo[] {info};
}
private final String name = "Reginald";
private int cacheSize = DEFAULT_CACHE_SIZE;
private static final int DEFAULT_CACHE_SIZE = 200;
private long sequenceNumber = 1;
}
MBeanNotification用来描述不同notification实例的特征。通过Jconsole,定于通知,当属性变更时,就会收到通知。
Introducing MXBeans
MXBean是一种新类型的MBean,它提供了简单方式编码MBean,仅仅引用之前定义的几种类型。通过这种方式,我们可以确定你的MBean可以被任何客户端使用,包括远程客户端。MXBean提供了一种便利的方式绑定相关值。与MBean类似,MXBean通过Java接口来定义,XXMXBean,java累实现此接口。然而不像标准MBean,MXBean不需要java类被称为xx。在接口中定义的每个方法要么是属性要么是操作。标注@MXBean可以用来标注Java接口,而不需要Java接口名称遵循后缀MXBean。MXBeans背后的核心理念是类型诸如java.lang.manangement.MemoryUsage,它将在MXBean接口中被引用。java.lang.manangement.MemoryMXBean被映射成一组标准类型,被称为open type(在javax.management.openmbean中定义)。映射规则可参见MXBean规范,但是简单类型如int或string不会改变,然而复杂类型诸如MemoryUsage被 映射成标准类型CompositeDataSupport。
package com.example.mxbeans;
public interface QueueSamplerMXBean {
public QueueSample getQueueSample();
public void clearQueue();
}
package com.example.mxbeans;
import java.util.Date;
import java.util.Queue;
public class QueueSampler implements QueueSamplerMXBean {
private Queue<String> queue;
public QueueSampler(Queue<String> queue) {
this.queue = queue;
}
public QueueSample getQueueSample() {
synchronized (queue) {
return new QueueSample(new Date(), queue.size(), queue.peek());
}
}
public void clearQueue() {
synchronized (queue) {
queue.clear();
}
}
}
package com.example.mxbeans;
import java.beans.ConstructorProperties;
import java.util.Date;
public class QueueSample {
private final Date date;
private final int size;
private final String head;
@ConstructorProperties({"date", "size", "head"})
public QueueSample(Date date, int size, String head) {
this.date = date;
this.size = size;
this.head = head;
}
public Date getDate() {
return date;
}
public int getSize() {
return size;
}
public String getHead() {
return head;
}
}
package com.example.mxbeans;
import java.lang.management.ManagementFactory;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import javax.management.MBeanServer;
import javax.management.ObjectName;
public class Main {
public static void main(String[] args) throws Exception {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName name =
new ObjectName("com.example.mxbeans:type=QueueSampler");
Queue<String> queue = new ArrayBlockingQueue<String>(10);
queue.add("Request-1");
queue.add("Request-2");
queue.add("Request-3");
QueueSampler mxbean = new QueueSampler(queue);
mbs.registerMBean(mxbean, name);
System.out.println("Waiting...");
Thread.sleep(Long.MAX_VALUE);
}
}
运行Main类,启动Jconsole,可以看到在接口中定义的方法getQueueSample返回的对象被映射成CompositeType。
//jmxclient来获取
MBeanServer mbs = ...whatever...;
ObjectName name = new ObjectName("com.example.mxbeans:type=QueueSampler");
CompositeData queueSample = (CompositeData) mbs.getAttribute(name,
"QueueSample");
int size = (Integer) queueSample.get("size");
//使用proxy方式
MBeanServer mbs = ...whatever...;
ObjectName name = new ObjectName("com.example.mxbeans:type=QueueSampler");
QueueSamplerMXBean proxy = JMX.newMXBeanProxy(mbs, name,
QueueSamplerMXBean.class);
QueueSample queueSample = proxy.getQueueSample();
int size = queueSample.getSize();