JMX(Java Management Extension)学习
基本概念
JMX(Java Management Extensions)是一个为应用程序植入管理功能的框架。
JMX让程序有被管理的功能,例如你开发一个WEB网站,它是在24小时不间断运行,那么你肯定会对网站进行监控,如每天的UV、PV是多少;又或者在业务高峰的期间,你想对接口进行限流,就必须去修改接口并发的配置值。
JMX框架主要由以下几层构成:
- 探针层(Probe Level)/设备层(Instrumentation Level)
- 代理层(Agent Level)
- 远程管理层(Remote Management Level)
它们之间的关系如下图所示:

需要通过JMX服务获得被管理对象信息的程序,就是通过远程管理层来与具体的MBean进行交互的。
分别介绍一下比较重要的一些概念:
- MBean(Managed Bean)
通常是一个 Java 类,它提供接口可以使这个类具有可以被管理(能够成功注册到server上)的功能。它通常代表我们想要实际管理的一个程序,或者一个设备等等,这是我们用MBean的规范将管理对象封装了起来。
- MBeanServer
是管理MBean的一个 Java 类,你需要向 MBeanServer 注册一个 MBean 后,这个 MBean 才会真正具备被管理的能力,MBeanServer 还提供了查询功能和注册监听器的功能,sun 提供的只是接口,不同的 JMX 实现中的 MBean server 实现也不同。
- JMX Agent
Agent 是 MBean Server 的容器,主要为了管理一系列的 MBean,并且提供的一系列的服务,通常有MBean relationships, dynamically loading classes, simple monitoring services, timers。Agent 可以利用 Protocol adapters(例如 HTTP 和 SNMP)和 connectors(RMI 和Jini)使不同的客户端可以访问 MBean。
- Protocol adapters 和 connectors
适配器和连接器主要使不同的协议和客户端可以使用这个 Agent,一个 Agent 中可以有多个 Protocol adapters 和 connectors,这样管理起 MBean 来就更方便了(有多种类型的客户端和协议可以操作 MBean)。注意,Protocol adapters 和 connectors 通常也是 MBean。
MBean的种类
- standard MBean:需要定义MBean接口,接口中包含需要被管理的资源,并编写MBean接口的实现类。接口和实现类的命名必须满足一定规范,若实现类名为Classname,则接口的命名必须为ClassNameMBean。
- dynamic MBean:必须实现javax.management.DynamicMBean接口,所有的属性,方法都在运行时定义。
- open MBean:此MBean的规范还不完善,正在改进中
- model MBean:与标准和动态MBean相比,你可以不用写MBean类,只需使用javax.management.modelmbean.RequiredModelMBean即可。RequiredModelMBean实现了ModelMBean接口,而ModelMBean扩展了DynamicMBean接口,因此与DynamicMBean相似,Model MBean的管理资源也是在运行时定义的。与DynamicMBean不同的是,DynamicMBean管理的资源一般定义在DynamicMBean中(运行时才决定管理那些资源),而model MBean管理的资源并不在MBean中,而是在外部(通常是一个类),只有在运行时,才通过set方法将其加入到model MBean中。
StandardMBean
从零开始玩转JMX(一)——简介和Standard MBean
MXBean相比MBean支持更复杂数据类型的类属性管理
DynamicBean
ModelMBean
JMX的实现方式
StandardMBean的使用方法
- 定义MBean接口
- 编写MBean接口实现类
- 创建MBeanServer类,并向server注册MBean类(server.registerMBean(实现类对象,ObjectName)) 【ObjectName取名是有规范的,格式为:“域名:name=MBean名称”,其中域名和MBean的名称可以任意取。这样定义后,就可以唯一标识我们定义的这个MBean的实现类了。】
- 为了查看实现状态,可以再加一个Thread.sleep(Long.MAX_VALUE),然后用JConsole工具查看。
JMX服务的访问方式
JMX服务可以有多种方式对其进行连接和使用,也有不同的展现方式,但内容都是相同的。
1.JDK自带工具JConsole(jdk/bin/jconsole.exe)
首先连接JMX服务。
JMX服务或者是本地提供,或者是远程提供,本地提供可以直接在jconsole的连接界面上显示,选中连接即可。远程提供的连接,则需要输入远程地址和端口号,并且如果设置了帐号密码还需要输入帐号密码,然后连接。

- 连接成功后,可以看到如文件目录形式展现的MBean,可以点击展开,查看属性,或者实时调用方法(在MBean接口实现类中实现的非属性相关的get/set方法都可以调用)。
2.通过JMX提供的工具页访问
这里需要到导入外部jar包jdmk
package jmx;
import java.lang.management.ManagementFactory;
import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import com.sun.jdmk.comm.HtmlAdaptorServer;
public class HelloAgent
{
public static void main(String[] args) throws JMException, Exception
{
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectName helloName = new ObjectName("jmxBean:name=hello");
//create mbean and register mbean
server.registerMBean(new Hello(), helloName);
//这里需要对Html适配器的MBean进行注册,并启动适配器,这样就可以通过网页来使用JMX。
ObjectName adapterName = new ObjectName("HelloAgent:name=htmladapter,port=8082");
HtmlAdaptorServer adapter = new HtmlAdaptorServer();
server.registerMBean(adapter, adapterName);
adapter.start();
}
}
访问地址:http://localhost:8082,点击name=hello:

3.通过客户端程序进行远程访问(RMI)
当然,需要先启动JMX服务,并监听端口才可以访问。
package jmx;
import java.io.IOException;
import javax.management.Attribute;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
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 IOException, Exception, NullPointerException
{
/**
* JMX提供服务的url
* @type {JMXServiceURL}
*/
JMXServiceURL url = new JMXServiceURL
("service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi");
/**
* JMX服务连接器,用于发起连接
* @type {[type]}
*/
JMXConnector jmxc = JMXConnectorFactory.connect(url,null);
/**
* 从JMX服务连接器上获取的MBeanServer连接器。
* @type {[type]}
*/
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
//ObjectName的名称与前面注册时候的保持一致
ObjectName mbeanName = new ObjectName("jmxBean:name=hello");
System.out.println("Domains ......");
//获得所有server下的域名
String[] domains = mbsc.getDomains();
for(int i=0;i<domains.length;i++)
{
System.out.println("domain[" + i + "]=" + domains[i] );
}
//获得所有注册在该server上的MBean数目
System.out.println("MBean count = " + mbsc.getMBeanCount());
//设置指定Mbean的特定属性值
//这里的setAttribute、getAttribute操作只能针对bean的属性
//例如对getName或者setName进行操作,只能使用Name,需要去除方法的前缀
mbsc.setAttribute(mbeanName, new Attribute("Name","杭州"));
mbsc.setAttribute(mbeanName, new Attribute("Age","1990"));
String age = (String)mbsc.getAttribute(mbeanName, "Age");
String name = (String)mbsc.getAttribute(mbeanName, "Name");
System.out.println("age=" + age + ";name=" + name);
/**
* 通过JMX调用MBean实例的方法
*/
//方法一
//通过获得代理调用MBean实例的方法
HelloMBean proxy = MBeanServerInvocationHandler.
newProxyInstance(mbsc, mbeanName, HelloMBean.class, false);
proxy.helloWorld();
proxy.helloWorld("migu");
proxy.getTelephone();
//方法二
//通过msbc的invoke方法调用MBean实例的方法,只针对非属性的相关的方法(get/set)
//例如invoke不能对getName方法进行调用
mbsc.invoke(mbeanName, "getTelephone", null, null);
mbsc.invoke(mbeanName, "helloWorld",
new String[]{"I'll connect to JMX Server via client2"}, new String[]{"java.lang.String"});
mbsc.invoke(mbeanName, "helloWorld", null, null);
}
}
JMX——Notifications
JMX API定义了一种机制,使MBean能生成通知,如当信号状态改变,检测到事件或者一个问题时。
通知模型仅仅涉及了在同一个JMX代理中的管理构件之间的事件传播。JMX通知模型依靠以下几个部分:
- Notification,一个通用的事件类型,该类标识事件的类型,可以被直接使用,也可以根据传递的事件的需要而被扩展。
- NotificationListener接口,接受通知的对象需实现此接口。
- NotificationFilter接口,作为通知过滤器的对象需实现此接口,为通知监听者提供了一个过滤通知的过滤器。
- NotificationBroadcaster接口,通知发送者需实现此接口,该接口允许希望得到通知的监听者注册。
发送一个通用类型的通知,任何一个监听者都会得到该通知。因此,监听者需提供过滤器来选择所需要接受的通知。任何类型的MBean,标准的或动态的,都可以作为一个通知发送者,也可以作为一个通知监听者,或两者都是。
要生成通知,MBean必须实现NotificationEmitter接口或继承NotificationBroadcasterSupport类。要发送一个通知必须构造Notification类的实例或者子类(如NotificationChangedAttribute),通知实例产生后,由NotificationBroadcasterSupport的sendNotification方法发送通知。
- 例子:
Step 1 :定义HelloMBean接口
package com.jmx.demo5;
public interface HelloMBean {
public void sayHello();
public int add(int x, int y);
public String getName();
public int getCacheSize();
public void setCacheSize(int size);
}
Step 2 :编写HelloMBean的实现类Hello
package com.jmx.demo5;
import javax.management.AttributeChangeNotification;
import javax.management.MBeanNotificationInfo;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
//MBean must extends NotificationBroadcasterSupport or implements NotificationEmitter
public class Hello extends NotificationBroadcasterSupport implements HelloMBean {
private final String name = "Reginald";
private int cacheSize = DEFAULT_CACHE_SIZE;
private static final int DEFAULT_CACHE_SIZE = 200;
private long sequenceNumber = 1;
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);
/**
* To send a notification,you need to construct an instance of class
* Notification or a Subclass(such as AttributeChangedNotification),and
* pass the instance to NotificationBroadcastSupport.sendNotification.
*
*/
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 };
}
}
Step 3:创建MBeanServer,标识MBean,注册MBean,并运行Main方法:
package com.jmx.demo5;
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 name = new ObjectName("com.jmx.demo:type=Hello");
Hello mbean = new Hello();
mbs.registerMBean(mbean, name);
System.out.println("Waiting forever...");
Thread.sleep(Long.MAX_VALUE);
}
}
然后可以用jconsole打开JMX服务,查看运行结果:通知选项初始状态没有值,点击订阅后,通知项为0
!pic
更改CacheSize的值后,在观察通知选项,变为1
总结:
Notification可以用于监测任何有关MBean方法调用的信息,只要MBean实现类继承NotificationBroadcasterSupport类,然后在需要监测的方法中调用NotificationBroadcasterSupport处继承来的sendNotification(Notification n)方法即可,而方法的参数是一个Notification实例,需要传入相关的通知信息。
JMX(Java Management Extension)学习的更多相关文章
- Java Management Extensions (JMX) Flume
Lesson: Overview of the JMX Technology (The Java™ Tutorials > Java Management Extensions (JMX)) h ...
- JAVA 基础知识学习笔记 名称解释
Java ee: IDE: itegrity development environment 集成开发环境 JMS: java Message Service java 信息服务 JM ...
- Java Management Extensions (JMX) - Best Practices 最佳实践
Java Management Extensions (JMX) - Best Practices 注意,本文一些管理可能与JMX API或JSR 77 (J2EE management)不一致.它们 ...
- Java虚拟机JVM学习05 类加载器的父委托机制
Java虚拟机JVM学习05 类加载器的父委托机制 类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap ...
- Java虚拟机JVM学习02 类的加载概述
Java虚拟机JVM学习02 类的加载概述 类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对 ...
- JCE, Java Cryptography Extension
JCE, Java Cryptography Extension Java 8 JCE下载地址: http://www.oracle.com/technetwork/java/javase/downl ...
- Java:NIO 学习笔记-1
Java:NIO 学习笔记-1 说明:本笔记是根据bilibili上 尚硅谷 的课程 NIO视频 而做的笔记 主要内容 Java NIO 简介 Java NIO 与 IO 的主要区别 缓冲区(Buff ...
- JAVA GUI编程学习笔记目录
2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...
- 一位资深程序员大牛给予Java初学者的学习路线建议
java学习这一部分其实也算是今天的重点,这一部分用来回答很多群里的朋友所问过的问题,那就是我你是如何学习Java的,能不能给点建议?今天我是打算来点干货,因此咱们就不说一些学习方法和技巧了,直接来谈 ...
随机推荐
- 两篇很好的EPG相关文章
两篇很好的EPG相关文章 原文地址:http://blog.sina.com.cn/s/blog_53220cef0100pi8j.html 1 基于DVB-SI的数字有线电视机顶盒节目指南的设计实现 ...
- 脸书VS微软,为何“老年创业者”更担忧AI失控?
作为互联网行业最知名的大会之一,近日举行的微软Build 2017大会,却增加了与以往不同的"调味品".除了新技术.智能硬件.系统.平台之外,微软CEO纳德拉在大会上对科技带给人类 ...
- 先治再扶,重灾区后的P2P你还敢投吗?
互联网强大的包容性和创新性,给予很多新生事物成长的空间.而其全面普及与快速传播的特性,也让任何事物都像被放在放大镜乃至显微镜下,几乎无形遁形.这样一来,新生事物很容易被"神化" ...
- 关于AJAX方法
ajax的方法每次都记不住这次特意找了资料做了归总: 在这里记录一下. 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为String类型的参数, ...
- 进阶之路 | 奇妙的Handler之旅
前言 本文已经收录到我的Github个人博客,欢迎大佬们光临寒舍: 我的GIthub博客 需要已经具备的知识: Handler的基本概念及使用 学习导图: 一.为什么要学习Handler? 在Andr ...
- Springboot 2.2.x 默认不支持put、delete等请求方式
springboot 2.2.x 默认不支持put delete等请 原因:springboot默认关闭了对它们的支持,只要在application.properties里面打开即可 spring.m ...
- 解决ionic2/ionic3轮播图切换页面或者点击过后不自动轮图
我们在ionic2/ionic3开发的过程中会出现切换页面或者滑动切换轮播图出现轮播图不再轮播的情况,这其实需要一些配置. 首先在运用到轮播图的component中引入 import {ViewChi ...
- 三年前端,面试思考(头条蚂蚁美团offer)
小鱼儿本人985本科,软件工程专业,前端.工作三年半,第一家创业公司,半年.第二家前端技术不错的公司,两年半.第三家,个人创业半年.可以看出,我是个很喜欢折腾的人,大学期间也做过很多项目,非常愿意参与 ...
- python从一个目录中复制全部文件图片至另一个目录中,及删除指定目录中的图片
import shutil import os #目录自己改一下即可,复制 path = "./static/imgs/" new_path = "./static/up ...
- 7,MapReduce基础
目录 MapReduce基础 一.关于MapReduce 二.MapReduce的优缺点 三.MapReduce的执行流程 四.编写MapReduce程序 五.MapReduce的主要执行流程 Map ...