一句话介绍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,那么:

这里写图片描述

这里写图片描述

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值