JMX(Java Management Extensions:即java管理扩展)是一个为应用程序,设备,系统等植入管理功能的框架,
JMX可以跨越一系列异构操作系统平台,系统体系架构和网络传输协议,灵活的开发无缝集成的系统,网络和服务管理应用.
应用场景:在一个系统中通常会有一些配置信息,例如服务器的IP地址和端口号,并且这些信息可能在系统运行的过程中经常需要改动,
面对这样的问题,怎么办呢?如下提供了四种解决方法.
1.一种方法是:将这些信息写死在代码里,当需要修改某些配置时,修改代码,然后将修改完的代码重新编译,将服务重新部署,并重新启动.
2.二种方法是:用配置文件来保存这些信息,省去了编译代码步骤,但是仍然需要重新启动服务.
3.三种方法是:用配置文件来保存这些信息,并让系统在运行时定期检查配置文件是否发生变化,如果发生变化重新读取数据放入缓存中,
这种方法是经常用的,但是额外增加了系统的繁琐性.
4.四种方法是:JMX为我们提供了更好的解决方案,我们可以把配置信息封装在一个称为MBean的对象中,
JMX提供了现成的用户接口(例如jconsole)使我们在系统运行过程中修改这些信息,并且不需要重启服务.
JDK工具套装中的jconsole是一个JMX兼容的图形界面工具,它能够连接到本地或远程的JVM,检测JVM的运行情况,
例如内存使用情况,线程的数量,已装入类的数目等,jconsole将这些JVM的数据以图形化的方式直观展现给用户.
JMX机构分为三层:自下向上依次是:设备层,代理层和分布式服务层.
设备层:定义成包括所有被管理和监测的资源,我们把这些资源统称为托管资源,托管资源被包装成一个MBean,
以便资源能够被JMX兼容的应用程序(例如jconsole)所管理.MBean共有四种类型:标准Bean,动态Bean,开放Bean和模型Bean.
代理层:代理层的实现是MBeanServer对象,所有的MBean对象都需要注册到MBeanServer上,以便被查询和控制.
分布式服务:分布式服务定义了JMX应用程序所需的接口,JMX应用程序通过该接口与MBean进行交互.
JMX约定:注册MBeanServer的MBean名称后缀必须是MBean,否则JMX无法识别.例如如果想将类名Log(包含三个属性id,name,log)的类注册到JMX,
需要为Log类定义接口LogMBean.在LogMean中如果包含属性的get方法,那么会在jconsole窗口中对应的属性列表中看到,
如果定义了其他方法(非get方法),会在jconsole窗口中对应的操作列表中看到.
下面通过一个简单的实例来学习一下JMX的使用,实例目的:控制各个模块的日志是否记录.
JMX可以跨越一系列异构操作系统平台,系统体系架构和网络传输协议,灵活的开发无缝集成的系统,网络和服务管理应用.
应用场景:在一个系统中通常会有一些配置信息,例如服务器的IP地址和端口号,并且这些信息可能在系统运行的过程中经常需要改动,
面对这样的问题,怎么办呢?如下提供了四种解决方法.
1.一种方法是:将这些信息写死在代码里,当需要修改某些配置时,修改代码,然后将修改完的代码重新编译,将服务重新部署,并重新启动.
2.二种方法是:用配置文件来保存这些信息,省去了编译代码步骤,但是仍然需要重新启动服务.
3.三种方法是:用配置文件来保存这些信息,并让系统在运行时定期检查配置文件是否发生变化,如果发生变化重新读取数据放入缓存中,
这种方法是经常用的,但是额外增加了系统的繁琐性.
4.四种方法是:JMX为我们提供了更好的解决方案,我们可以把配置信息封装在一个称为MBean的对象中,
JMX提供了现成的用户接口(例如jconsole)使我们在系统运行过程中修改这些信息,并且不需要重启服务.
JDK工具套装中的jconsole是一个JMX兼容的图形界面工具,它能够连接到本地或远程的JVM,检测JVM的运行情况,
例如内存使用情况,线程的数量,已装入类的数目等,jconsole将这些JVM的数据以图形化的方式直观展现给用户.
JMX机构分为三层:自下向上依次是:设备层,代理层和分布式服务层.
设备层:定义成包括所有被管理和监测的资源,我们把这些资源统称为托管资源,托管资源被包装成一个MBean,
以便资源能够被JMX兼容的应用程序(例如jconsole)所管理.MBean共有四种类型:标准Bean,动态Bean,开放Bean和模型Bean.
代理层:代理层的实现是MBeanServer对象,所有的MBean对象都需要注册到MBeanServer上,以便被查询和控制.
分布式服务:分布式服务定义了JMX应用程序所需的接口,JMX应用程序通过该接口与MBean进行交互.
JMX约定:注册MBeanServer的MBean名称后缀必须是MBean,否则JMX无法识别.例如如果想将类名Log(包含三个属性id,name,log)的类注册到JMX,
需要为Log类定义接口LogMBean.在LogMean中如果包含属性的get方法,那么会在jconsole窗口中对应的属性列表中看到,
如果定义了其他方法(非get方法),会在jconsole窗口中对应的操作列表中看到.
下面通过一个简单的实例来学习一下JMX的使用,实例目的:控制各个模块的日志是否记录.
1.查看MBean类,直接看代码Log和LogMBean.
<span style="font-size:12px;">package com.ilucky.jmx.model;
/**
* @author IluckySi
* @date 20140730
*/
public class Log implements LogMBean {
private int id;
private String name;
private boolean log;
public Log(int id, String name, boolean log) {
this.id = id;
this.name = name;
this.log = log;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("修改日志审计模块名称为: " + name);
this.name = name;
}
public boolean isLog() {
return log;
}
public void setLog(boolean log) {
System.out.println("修改日志审计模块结果为: " + log);
this.log = log;
}
public void changeName(String name) {
setName(name);
}
public void changeLog(boolean log) {
setLog(log);
}
public void test1() {
System.out.println("测试1: Hello Word!");
}
public void test2(int a, int b) {
System.out.println("测试2: a + b = " + (a + b));
}
}
</span>
<span style="font-size:12px;">package com.ilucky.jmx.model;
/**
* @author IluckySi
* @date 20140730
*/
public interface LogMBean {
public int getId();
public String getName();
public boolean isLog();
public void changeName(String name);
public void changeLog(boolean log);
public void test1();
public void test2(int a, int b);
}
</span>
2.查看MBeanServer类,直接看代码MyMBeanServer.
<span style="font-size:12px;">package com.ilucky.jmx.server;
import java.lang.management.ManagementFactory;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
/**
* @author IluckySi
* @date 20140730
*/
public class MyMBeanServer {
public static MyMBeanServer instance;
private static MBeanServer mBeanServer;
public static MyMBeanServer getInstance() {
if(instance == null) {
instance = new MyMBeanServer();
}
return instance;
}
private MyMBeanServer() {
mBeanServer = ManagementFactory.getPlatformMBeanServer();
}
public void registerMBean(Object object, ObjectName objectName) {
try {
mBeanServer.registerMBean(object, objectName);
} catch (InstanceAlreadyExistsException e) {
System.out.println("向Jmx Server注册MBean发生问题: " + e.toString());
} catch (MBeanRegistrationException e) {
System.out.println("向Jmx Server注册MBean发生问题: " + e.toString());
} catch (NotCompliantMBeanException e) {
System.out.println("向Jmx Server注册MBean发生问题: " + e.toString());
}
}
}
</span>
3.最后看测试类MainTest.
<span style="font-size:12px;">package com.ilucky.jmx;
import javax.management.ObjectName;
import com.ilucky.jmx.model.Log;
import com.ilucky.jmx.model.LogMBean;
import com.ilucky.jmx.server.MyMBeanServer;
/**
* @author IluckySi
* @date 20140730
*/
public class MainTest {
public static void main(String[] args) {
try {
//获取MBeanServer并注册MBean.
MyMBeanServer myMBeanServer = MyMBeanServer.getInstance();
ObjectName objectName = new ObjectName("com.ilucky.jmx:model=LogMBean");
LogMBean logMBean = new Log(21, "司冬雪", false);
myMBeanServer.registerMBean(logMBean, objectName);
//让服务一直处于等待中以便测试.
Thread.sleep(Integer.MAX_VALUE);
} catch (Exception e) {
System.out.println("测试发生问题: " + e.toString());
}
}
}
/**
执行结果:
修改日志审计模块名称为: sdx
修改日志审计模块名称为: sdx2
修改日志审计模块结果为: true
修改日志审计模块结果为: false
测试1: Hello Word!
测试1: Hello Word!
测试2: a + b = 33
测试2: a + b = 335
*/
</span>
4.最后在cmd窗口运行jconsole指令,打开图形界面(简单截了几张图).