一句话介绍JMX——JMX基础

what?

The Java Management Extensions (JMX) API is a standard API for management and monitoring of resources such as applications, devices, services, and the Java virtual machine.
一句话:对系统资源进行管理的规范API.

where to use?

ypical uses of the JMX technology include:

  • Consulting and changing application configuration
  • Accumulating statistics about application behavior and making them available
  • Notifying of state changes and erroneous conditions.

一句话 典型应用:改变、查看程序配置;收集计算程序行为数据;通知、告警。

import notion

An MBean is a managed Java object, similar to a JavaBeanTM, that follows the design patterns set forth in the instrumentation level of the JMX specification.
(4 kinds MBean)
- standard MBeans
- dynamic MBeans
- open MBeans
- model MBeans.

MBeans expose a management interface: a set of readable and/or writable attributes and a set of invokable operations, along with a self-description. The management interface does not change throughout the life of an MBean instance.

一句话 MBean是JMX的核心,MBean类似与javaBean,我们通过MBean暴漏出的接口去获取MBean所检测程序的各种信息。

standard MBean

A standard MBean is defined by writing a Java interface called SomethingMBean and a Java class called Something that implements that interface.
A standard MBean is composed of the MBean interface which lists the methods for all exposed attributes and operations, and the class which implements this interface and provides the functionality of the instrumented resource.

一句话,standard MBean 就是 一个实现了 接口:***MBean 的实现类(如TimerMBean,自己去看API docs),这里暴漏出获取信息的方法,以便活动你要的各种信息。

例子:

/* HelloMBean.java - MBean interface describing the management operations and attributes for the Hello World MBean. In this case there are two operations, "sayHello" and "add", and two attributes, "Name" and "CacheSize". */

package com.example.mbeans;

public interface HelloMBean {
    // operations

    public void sayHello();
    public int add(int x, int y);

    // attributes

    // a read-only attribute called Name of type String
    public String getName();

    // a read-write attribute called CacheSize of type int
    public int getCacheSize();
    public void setCacheSize(int size);
}
/* Hello.java - MBean implementation for the Hello World MBean. This class must implement all the Java methods declared in the HelloMBean interface, with the appropriate behavior for each one. */

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;
    }

    /* Getter for the Name attribute. The pattern shown here is frequent: the getter returns a private field representing the attribute value. In our case, the attribute value never changes, but for other attributes it might change as the application runs. Consider an attribute representing statistics such as uptime or memory usage, for example. Being read-only just means that it can't be changed through the management interface. */
    public String getName() {
    return this.name;
    }

    /* Getter for the CacheSize attribute. The pattern shown here is frequent: the getter returns a private field representing the attribute value, and the setter changes that field. */
    public int getCacheSize() {
    return this.cacheSize;
    }

    /* Setter for the CacheSize attribute. To avoid problems with stale values in multithreaded situations, it is a good idea for setters to be synchronized. */
    public synchronized void setCacheSize(int size) {
    this.cacheSize = size;

    /* In a real application, changing the attribute would typically have effects beyond just modifying the cacheSize field. For example, resizing the cache might mean discarding entries or allocating new ones. The logic for these effects would be here. */
    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;
}
/* Main.java - main class for Hello World example. Create the HelloWorld MBean, register it, then wait forever (or until the program is interrupted). */

package com.example.mbeans;

import java.lang.management.*;
import javax.management.*;

public class Main {
    /* For simplicity, we declare "throws Exception". Real programs will usually want finer-grained exception handling. */
    public static void main(String[] args) throws Exception {
    // Get the Platform MBean Server attention!
    MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

    // Construct the ObjectName for the MBean we will register
    ObjectName name = new ObjectName("com.example.mbeans:type=Hello");

    // Create the Hello World MBean
    Hello mbean = new Hello();

    // Register the Hello World MBean attention! 
    mbs.registerMBean(mbean, name);

    // Wait forever
    System.out.println("Waiting forever...");
    Thread.sleep(Long.MAX_VALUE);
    }
}

According to the JMX specification, an MBean interface consists of named and typed attributes that are readable and possibly writable, and named and typed operations that can be invoked by the applications that are managed by the MBean.

**一句话:
接口 以 **MBean 定义,并且这个MBean接口要写明 属性(如 , Name , CacheSize) 名称,类型,并且暴漏出去获取或设置他们的方法以及一些操作。如例子中add() and sayHello()。
用一个JMX agent去管理 MBean:JMX agent 的核心组件是the MBean server,管理之前要先注册进去。

MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
通过调用java.lang.management.ManagementFactory.getPlatformMBeanServer()方法 获取运行在platform上的MBean Server.如果platform没有,则会自动获取一个(通过MBeanServerFactory.createMBeanServer())。

发送消息

MBeans can generate notifications, for example to signal a state change, a detected event, or a problem.

不要忘了,MBean可以监测一个事件,问题,状态,并因此发送消息通知

1.实现 NotificationBroadcasterSupport 或者 它的子接口 NotificationEmitter.
2.创建一个javax.management.Notification 实例或者它的子类(AttributeChangedNotification),并把它传入 NotificationBroadcasterSupport.sendNotification.

 package com.example.mbeans;

import javax.management.*;

import com.test.mbean.HelloMBean;

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;
}

主要注意 Hello.java 其余与上例类似,略。
1.它继承了NotificationBroadcasterSupport (该类实现了NotificationEmitter接口)
2.实例化一个Notification 并通过sendNotification(…)发送
聪明的农夫,自己试一试吧!

MXBean

what?
就是MBean的加强版,加强在于 提前为我们定义好了一系列通用类型。
how to use?
首先,定义一个**MXBean接口用来实现 。实现类与Standard MBean 不同,你可以爱叫啥叫啥。

package jmx_examples.MXBean.com.example.mxbeans;

public interface QueueSamplerMXBean {
    /** read-only attribute "QueueSample" */
    public QueueSample getQueueSample();

    /** an operation "clearQueue" */
    public void clearQueue();
}

与定义一个StandardMBean 接口一样。

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(); 
        } 
    } 
} 

实现接口,没啥好说的。

/** * QueueSample.java - Java type representing a snapshot of a given queue. * It bundles together the instant time the snapshot was taken, the queue * size and the queue head. */

package jmx_examples.MXBean.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;
    }
}

注释@ConstructorProperties({“date”, “size”, “head”}),运行时可以根据参数找到对应的get方法。这样声明后,就代表他们三个有getXxx方法。
其实,因为MXBean模式调用QueueSample 的所有get方法,用来把一个实例转化为一个CompositeData,用@ConstructorProperties({“date”, “size”, “head”})注释,在需要的时候可以再次重构一个QueueSample 实例。(其实我也不完全懂,高手请补充!呵呵)

其实,MXBean 可以把一个复杂的(attribute)对象,映射为一个CompositeDataSupport类( so-called Open Types ),String,int等简单类型不算。

当然,我们的QueueSample本身就是一个复杂类型,并且可以把这个复杂类型。

public class Main {
    /* For simplicity, we declare "throws Exception". Real programs will usually want finer-grained exception handling. */
    public static void main(String[] args) throws Exception {
        // Get the Platform MBean Server
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

        // Construct the ObjectName for the MBean we will register
        ObjectName name =
                new ObjectName("com.example.mxbeans:type=QueueSampler");

        // Create the Queue Sampler MXBean
        Queue<String> queue = new ArrayBlockingQueue<String>(10);
        queue.add("Request-1");
        queue.add("Request-2");
        queue.add("Request-3");
        QueueSampler mxbean = new QueueSampler(queue);

        // Register the Queue Sampler MXBean
        mbs.registerMBean(mxbean, name);

        // Wait forever
        System.out.println("Waiting...");
        Thread.sleep(Long.MAX_VALUE);
    }
}

如果你不用**MXBean结果,不如说把上例改为QueueSamplerMBean,那么:

一句话介绍JMX——JMX基础_第1张图片

because it would not be in its class path。这是因为,MBean 的复杂类型属性无法载入classPath,当你试图获取它的属性attribute时,报ClassNotFoundException .也就是说,只用MXBean这种模式,才可以把复杂类型转为更细的类型(也就是OpenType).

如果你想动态的获取JMX客户端的一个MXBean,那么这么做:

1.直接获取

Generically, using the following code.
CODE EXAMPLE 2-9 Accessing an MXBean directly

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");

2.通过代理获取

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(); 

MBean里也有一个代理,通过JMX.newMBeanProxy获取,与newMXBeanProxy类似,自己试一试。

MBean Descriptors

what?
就是用来描述一个MBean的描述信息,Descriptors给你一个方便的方式,为你的MBeans加上一些Metadata.
其他没啥好说的,自己下个例子,自己看去吧。

参考:

http://docs.oracle.com/javase/6/docs/technotes/guides/jmx/tutorial/essential.html#wp1055648

你可能感兴趣的:(jmx)