JMX 简介

JMX【Java Management Extensions】 java管理扩展。简而言之,它提供一个统一的接口来管理一些系统资源。例如,你可能需要在某一时刻手动的删除服务器内存中的数据。那可行的解决方案就是提供一个页面,然后用户可在这个页面是做各种操作,然后发各种请求给服务器,然后服务器相应用户请求,做相应操作。而利用jmx就不需要自己去创建页面,只需将所要提供的服务注册到jmx,利用原生的jconsole就能控制系统资源。

 

一 注册MBean并通过JConsole查看MBean

1.HelloMBean.java

 

package mbean;
public interface HelloMBean {
	public void sayHello();
	public void setName(String name);
	public String getName();
}

 2.Hello.java

 

package mbean;
public class Hello implements HelloMBean {
	private String name;
	@Override
	public void sayHello() {
		System.out.println("say hello...");
	}
	@Override
	public void setName(String name) {
		this.name=name;
	}
	@Override
	public String getName() {
		return name;
	}
}

 3.Main.java[注册MBean]

 

package mbean;
import java.lang.management.ManagementFactory;
import javax.management.MBeanServer;
import javax.management.ObjectName;
public class Main {
	public static void main(String[] args) throws Exception{
		System.out.println(System.getProperties());
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 
        ObjectName name = new ObjectName("com.example:type=Hello"); 
        Hello mbean = new Hello(); 
        mbs.registerMBean(mbean, name); 
       
        System.out.println("Waiting forever..."); 
        Thread.sleep(Long.MAX_VALUE); 
	}
}

 编写MBean接口时,命名必须以MBean结尾,并且相应的实现类【这里是Hello.java】必须和接口【这里是HelloMBean.java】在同一包下。

4. 通过JConsole查看注册的MBean。



 

 二 注册MXBean并通过JConsole查看

 

 1.QueueSample.java

package mxbean;
import java.util.Date;
public class QueueSample {
	private final Date date; 
    private final int size; 
    private final String 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; 
    } 
}

 2.QueueSamplerMXBean.java

package mxbean;
public interface QueueSamplerMXBean {
	public QueueSample getQueueSample(); 
    public void clearQueue(); 
}

 3.QueueSampler.java

package mxbean.impl;
import java.util.Date;
import java.util.Queue;
import mxbean.QueueSample;
import mxbean.QueueSamplerMXBean;
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();
		}
	}
}

  编写MXBean接口时,没有像MBean那么多约束。接口命名可以以MXBean结尾也可以不用,只需要在接口上添加@MXBean注解来表明这个是一个MXBean。而且实现了可以与接口在不同包。最重要的是MXBean可以定义复杂的数据类型。

 4 .Main.java[注册MXBean]

package mxbean;
import java.lang.management.ManagementFactory;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import mxbean.impl.QueueSampler;
public class Main {
	public static void main(String[] args) throws Exception {
		MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
		ObjectName mxbeanName = new ObjectName("com.example: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, mxbeanName);
		System.out.println("Waiting...");
		Thread.sleep(Long.MAX_VALUE);
	}
}

 5. 通过JConsole查看



 

三 使用JMX Notification

1.AnimalMBean.java

package notification;
public interface AnimalMBean {
	public void eat();
	public void sleep();
}

 2.Animal.java

package notification;
import javax.management.AttributeChangeNotification;
import javax.management.MBeanNotificationInfo;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
public class Animal extends  NotificationBroadcasterSupport implements AnimalMBean{
	int sequenceNumber=1;
	private String status="eat";
	@Override
	public void eat() {
		System.out.println("animal eats ...");
		
		Notification n = new AttributeChangeNotification(this,
                sequenceNumber++, System.currentTimeMillis(),
                "aniaml eats", "status", "String",
                status, "eat");

		sendNotification(n);
		status="eat";
	}

	@Override
	public void sleep() {
		System.out.println("animal sleeps...");
		Notification n = new AttributeChangeNotification(this,
                sequenceNumber++, System.currentTimeMillis(),
                "aniaml sleeps", "status", "String",
                status, "sleep");

		sendNotification(n);
		status="sleep";
	}
	
	@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};
    }
}

 

 3.Main.java

 

package notification;
import java.lang.management.ManagementFactory;
import javax.management.MBeanServer;
import javax.management.ObjectName;
public class Main {
	public static void main(String[] args) throws Exception{
		MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
		ObjectName mxbeanName = new ObjectName("com.example:type=Notification");
		Animal mxbean = new Animal();
		mbs.registerMBean(mxbean, mxbeanName);
		System.out.println("Waiting...");
		Thread.sleep(Long.MAX_VALUE);
	}
}

每当Animal类中eat或sleep方法是,都会向订阅者发送消息。

4. JConsole 演示



 点击Subscribe订阅



 

 点击sleep或eat任意按钮,触发相应操作



 在Notifications中会接收相应的消息

 

四 远程调用jmx。之前以上例子都是运行在本地的。只有本地的JConsole才能访问。

而要注册一个可供远程调用的MBean,必须暴露一个端口可供外部访问。

例如要将例1HelloMBean.java暴露出去

必须在启动参数中加入如下参数

-Dcom.sun.management.jmxremote.port=9999 // 外部访问端口

-Dcom.sun.management.jmxremote.authenticate=false // 关闭验证

-Dcom.sun.management.jmxremote.ssl=false // 关闭ssl

1. 通过JConsole访问



 

输入远程jmx服务器的ip地址以及jmx暴露的端口号

2. 通过代码远程调用

Main.java

package remote.access;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
public class Main {
	public static void main(String[] args) throws Exception{
		JMXServiceURL url =  new JMXServiceURL("service:jmx:rmi:///jndi/rmi://127.0.0.7:9999/jmxrmi");
		JMXConnector jmxc = JMXConnectorFactory.connect(url);
		MBeanServerConnection mbsc=jmxc.getMBeanServerConnection();
		ObjectName name = new ObjectName("com.example:type=Hello"); 
		mbsc.invoke(name, "sayHello",null,null);
	}
}

猜你喜欢

转载自antlove.iteye.com/blog/1900221
JMX
今日推荐