目录

java有一个动态管理应用程序的动能叫jmx(Java Management Extensions,即Java管理扩展)。它向外部提供了接口(主要是2种:jmxrmi和http),用于获取程序内部信息动态控制程序

jmx可以理解为jvm开了一个端口,通过该端口可以直接访问jvm堆中的对象(前提是该对象必须先注册到jmx,否则jmx允许你访问任何对象,太不安全了)

jmx工作过程

  1. 创建一个接口,接口名以MBean为后缀,如:ControllerMBean
    1. 以MBean为后缀的接口会自动被jmx管理
  2. 创建一个类Controller实现ControllerMBean接口
  3. 注册Controller类,注册之后可以提供服务,服务分2种
    1. 第一种服务,为jconsole提供管理接口,可以通过jconsole连接并管理应用程序
    2. 第二种服务,提供一个HTTP的api,通过HTTP请求管理应用程序

代码如下

代码依赖2个jar包

ControllerMBean.java

public interface ControllerMBean {


	public void setName(String name);
	public String getName();
        public void setName1(String name1);
        public String getName1();
	
	public String status();
	public void start();
	public void stop();
	
}

Controller.java

public class Controller implements ControllerMBean {

	private String name;
	private String name1;

	public void setName(String name) {
		this.name = name;
		System.out.println("set name:"+name);
	}

	public String getName() {
		System.out.println("get name:"+name);
		return this.name;

	}
	public void setName1(String name1) {
		this.name1 = name;
		System.out.println("set name1:"+name1);
	}

	public String getName1() {
		System.out.println("get name1:"+name1);
		return this.name1;

	}

	public String status() {
		System.out.println("status");
		return "this is a Controller MBean,name is " + this.name;

	}

	public void start() {
		System.out.println("start");
		// TODO Auto-generated method stub
	}


	public void stop() {
		System.out.println("stop");
		// TODO Auto-generated method stub
	}
}

Main.java

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


public class Main {
    /**
     * @param args
     * @throws NullPointerException
     * @throws MalformedObjectNameException
     * @throws NotCompliantMBeanException
     * @throws MBeanRegistrationException
     * @throws InstanceAlreadyExistsException
     */
    public static void main(String[] args) throws MalformedObjectNameException,Exception {
        //获得MBeanServer实例
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();//可在jconsole中使用
        //创建MBean
        ControllerMBean controller = new Controller();
        System.out.println(controller.hashCode());
        //将MBean注册到MBeanServer中
        mbs.registerMBean(controller, new ObjectName("MyappMBean:type=MyMetric"));

        //创建适配器,用于能够通过浏览器(http)访问MBean,如果没有以下四句代码,则只能通过jconsole管理
//        HtmlAdaptorServer adapter = new HtmlAdaptorServer();
//        adapter.setPort(9797);
//        mbs.registerMBean(adapter, new ObjectName(
//                "MyappMBean:name=html"));
//        adapter.start();


        Thread.sleep(Long.MAX_VALUE);
    }
}

客户端(读取/修改指标)

import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;
import javax.management.JMX;
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 Client {
    
    public static void main(String[] args) throws Exception {
        JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi");
        JMXConnector jmxc = JMXConnectorFactory.connect(url, null);


        System.out.println("-------------- All Domain -----------------");
        MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();

        // Get domains from MBeanServer
        String domains[] = mbsc.getDomains();
        Arrays.sort(domains);
        for (String domain : domains) {
            System.out.println("\tDomain = " + domain);
        }

        System.out.println("-------------- MBean -----------------");
        System.out.println("MBean count = " + mbsc.getMBeanCount());
        Set<ObjectName> names = new TreeSet<ObjectName>(mbsc.queryNames(null, null));
        for (ObjectName name : names) {
            System.out.println("\tObjectName = " + name);
        }

        System.out.println("-------------- set metric -----------------");

        ObjectName mbeanName = new ObjectName("MyappMBean:type=MyMetric");
        ControllerMBean mbeanProxy = JMX.newMBeanProxy(mbsc, mbeanName, ControllerMBean.class, true);
        mbeanProxy.setName("fang1");
        System.out.println("set name: fang1");

        System.out.println("-------------- get metric -----------------");
        System.out.println("getname = " + mbeanProxy.getName());
    }
}