Java----------JMX规范
链接:https://www.zhihu.com/question/36688387/answer/68667704
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
JMX是一种JAVA的正式规范,它主要目的是让程序有被管理的功能。
那么怎么理解所谓的“被管理”呢?试想你开发了一个软件(如WEB网站),它是在24小时不简断运行的,那么你可能会想要“监控”这个软件的运行情况,比如收到了多少数据,有多少人登录等等。或者你又想“配置”这个软件,比如现在访问人数比较多,你想把数据连接池设置得大一些;每天的UV、PV是多少;又或者在业务高峰的期间,你想对接口进行限流,就必须去修改接口并发的配置值。
应用场景:中间件软件WebLogic的管理页面就是基于JMX开发的,而JBoss则整个系统都基于JMX构架。
对于一些参数的修改,网上有一段描述还是比较形象的:
1、程序初哥一般是写死在程序中,到要改变的时候就去修改代码,然后重新编译发布。
2、程序熟手则配置在文件中(JAVA一般都是properties文件),到要改变的时候只要修改配置文件,但还是必须重启系统,以便读取配置文件里最新的值。
3、程序好手则会写一段代码,把配置值缓存起来,系统在获取的时候,先看看配置文件有没有改动,如有改动则重新从配置里读取,否则从缓存里读取。
4、程序高手则懂得物为我所用,用JMX把需要配置的属性集中在一个类中,然后写一个MBean,再进行相关配置。另外JMX还提供了一个工具页,以方便我们对参数值进行修改。
让开发者和管理者可以获取程序运行的状态以及动态的修改程序的相关配置。
SUN依据这个规范在JDK提供了JMX接口,而根据这个接口的实现则有很多种,比如Weblogic的JMX实现、MX4J、JBoss的JMX实现。
我们经常使用的JDK中SUN公司的实现在java.lang.management包下。
JMX架构图:
MBean 即 managed beans 被管理的Beans
<img src="https://pic4.zhimg.com/50/v2-53dcda2a13f51e1e0177bc0c2e166e27_hd.jpg" data-rawwidth="600" data-rawheight="468" class="origin_image zh-lightbox-thumb" width="600" data-original="https://pic4.zhimg.com/v2-53dcda2a13f51e1e0177bc0c2e166e27_r.jpg">
从图中我们可以看到,JMX的结构一共分为三层:
1、基础层:主要是MBean,被管理的资源。
MBean分为如下四种,我接下来主要介绍standard MBean
类型描述standard MBean这种类型的MBean最简单,它能管理的资源(包括属性,方法,时间)必须定义在接口中,然后MBean必须实现这个接口。它的命名也必须遵循一定的规范,例如我们的MBean为Hello,则接口必须为HelloMBean。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中。后面的例子会有详细介绍
2、适配层:MBeanServer,主要是提供对资源的注册和管理。
3、接入层:提供远程访问的入口。
JMX超详细解读 - 冬瓜蔡 - 博客园 这篇博客详细介绍了三种使用JMX的方式,下面我提供一下自己实现的例程
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.rmi.registry.LocateRegistry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectName;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;
import com.sun.jdmk.comm.HtmlAdaptorServer;
public class ApplicationServer
{
	private static HtmlAdaptorServer adaptorServer = null;
	private static javax.management.remote.JMXConnectorServer cs = null;
	private static Logger logger = null;
	private static ExecutorService cachedExecutors = null;
	private static void initExecutor()
	{
		cachedExecutors = Executors.newFixedThreadPool(2);
	}
	private static void exitExecutor()
	{
		cachedExecutors.shutdown();
	}
	public static void execute(final Runnable runnable)
	{
		cachedExecutors.execute(runnable);
	}
	private static void initLogger()
	{
		System.out.println("configuring log4j with log4j.xml");
		DOMConfigurator.configure("log4j.xml");
		logger = Logger.getLogger("root");
	}
	private static void initHtmlJMX() throws Exception
	{
		MBeanServer server = MBeanServerFactory.createMBeanServer();
		ObjectName helloName = new ObjectName("jmx:name=HelloWorld");
		server.registerMBean(new Hello(), helloName);
		ObjectName adapterName = new ObjectName("HelloAgent:name=htmladapter,port=8081");
		adaptorServer = new HtmlAdaptorServer();
		server.registerMBean(adaptorServer, adapterName);
		adaptorServer.start();
		logger.info("start jmx html server");
	}
	private static int initProtogenesisJMX() throws Exception
	{
		String port1Str = System.getProperty("com.jmxport1");
		String port2Str = System.getProperty("com.jmxport2");
		if (port1Str == null || port2Str == null)
		{
			logger.error("jmx端口未通过系统属性设置");
			return -1;
		}
		final int port1 = Integer.valueOf(port1Str);
		final int port2 = Integer.valueOf(port2Str);
		System.setProperty("java.rmi.server.randomIDs", "true");
		try
		{
			LocateRegistry.createRegistry(port2);
		}
		catch (java.rmi.server.ExportException ex)
		{
			logger.error("err", ex);
			return -1;
		}
		MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
		java.util.HashMap<String, Object> env = new java.util.HashMap<String, Object>();
		env.put("jmx.remote.x.password.file", "jmxremote.password");
		env.put("jmx.remote.x.access.file", "jmxremote.access");
		JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://127.0.0.1:" + port1 + "/jndi/rmi://127.0.0.1:" + port2
				+ "/jmxrmi");
		cs = JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
		try
		{
			cs.start();
		}
		catch (java.net.BindException ex)
		{
			logger.error("端口已被占用", ex);
			return -2;
		}
		return 0;
	}
	public static void exitHtmlJMX()
	{
		adaptorServer.stop();
	}
	public static void exitProtogenesisJMX() throws IOException
	{
		cs.stop();
	}
	public static void init() throws Exception
	{
		initLogger();
		// initHtmlJMX();
		initProtogenesisJMX();
		initExecutor();
	}
	public static void exit() throws IOException
	{
		//exitHtmlJMX();
		exitProtogenesisJMX();
		exitExecutor();
	}
	public static void main(String[] args) throws Exception
	{
		System.setProperty("com.jmxport1", String.valueOf(7000));
		System.setProperty("com.jmxport2", String.valueOf(7001));
		init();
		MBeanServer server = java.lang.management.ManagementFactory.getPlatformMBeanServer();
		ObjectName helloName = new ObjectName("jmxBean:name=stopper");
		server.registerMBean(new Stopper(), helloName);
	}
	public interface StopperMBean
	{
		void stop() throws IOException;
	}
	public static class Stopper implements StopperMBean
	{
		public void stop() throws IOException
		{
			ApplicationServer.exit();
		}
	}
}
import java.text.SimpleDateFormat;
import java.util.HashMap;
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 JMXClient
{
	/**
	 *
	 * @param args
	 *            host port username password bean name method ...params
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception
	{
		if ((args.length < 6) || (args.length % 2 != 0))
		{
			logErr("params error");
			return;
		}
		final String host = args[0];
		final int rmiPort = Integer.valueOf(args[1]).intValue();
		final String username = args[2];
		final String password = args[3];
		final ObjectName objectName = new ObjectName(args[4]);
		final String methodName = args[5];
		final HashMap<String, String[]> jmxParamsHashMap = new HashMap<String, String[]>();
		final String[] usernameAndPassword =
		{ username, password };
		jmxParamsHashMap.put("jmx.remote.credentials", usernameAndPassword);
		final String serviceUrl = new StringBuilder().append("service:jmx:rmi:///jndi/rmi://").append(host).append(":")
				.append(rmiPort).append("/jmxrmi").toString();
		final JMXServiceURL jmxServiceURL = new JMXServiceURL(serviceUrl);
		final JMXConnector jmxConnector = JMXConnectorFactory.connect(jmxServiceURL, jmxParamsHashMap);
		if (jmxConnector == null)
		{
			logErr(new StringBuilder().append("connect to jmx failed, url=").append(jmxServiceURL).toString());
			return;
		}
		log(new StringBuilder().append("JMXConnector=").append(jmxConnector.toString()).toString());
		Object[] paramsValue = null;
		String[] paramsClassName = null;
		final MBeanServerConnection mBeanServerConnection = jmxConnector.getMBeanServerConnection();
		final Object localObject = mBeanServerConnection.invoke(objectName, methodName, paramsValue, paramsClassName);
		log(new StringBuilder().append("invoke method success, name=").append(objectName).append(", operation=")
				.append(methodName).append(", retvalue=").append(localObject == null ? "void" : localObject.toString())
				.toString());
	}
	static void log(String paramString)
	{
		final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss : ");
		final StringBuilder sBuilder = new StringBuilder();
		sBuilder.append(simpleDateFormat.format(Long.valueOf(System.currentTimeMillis())));
		sBuilder.append(paramString);
		System.out.println(sBuilder.toString());
	}
	static void logErr(String paramString)
	{
		final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss : ");
		final StringBuilder sBuilder = new StringBuilder();
		sBuilder.append(simpleDateFormat.format(Long.valueOf(System.currentTimeMillis())));
		sBuilder.append(paramString);
		System.err.println(sBuilder.toString());
	}
}Java----------JMX规范的更多相关文章
- Java模块化规范之争(转载)
		经过近20年的发展,Java语言已成为今日世界上最成功.使用的开发者人数最多的语言之一,Java世界中无数商业的或开源的组织.技术和产品共同构成了一个无比庞大的生态系统. 与大多数开发人员的普遍认知不 ... 
- Java JMX 监管
		Java JMX 监管 JSR 规范系列目录(https://www.cnblogs.com/binarylei/p/10348178.html) JMX(Java Management Extens ... 
- JAVA语言规范-线程和锁章节之同步、等待和通知
		JAVA语言规范:线程和锁 1 同步 java编程语言提供了线程间通信的多种机制.这些方法中最基本的是同步化,此方法是使用监视器实现的.JAVA中每个对象与一个监视器相关联,一个线程可以加锁和解锁监视 ... 
- 转!!Java代码规范、格式化和checkstyle检查配置文档
		为便于规范各位开发人员代码.提高代码质量,研发中心需要启动代码评审机制.为了加快代码评审的速度,减少不必要的时间,可以加入一些代码评审的静态检查工具,另外需要为研发中心配置统一的编码模板和代码格式化模 ... 
- Java命名规范基础
		一.java命名规范 1.类和接口:由多个单词组成时,所有单词的首字母大写,如TestJava 2.变量名和方法(函数):由多个单词组成时,所有第一个单词的首字母小写,之后每一个单词的首字母大写,如: ... 
- 【转】Java代码规范
		[转]Java代码规范 http://blog.csdn.net/huaishu/article/details/26725539 
- JAVA编程规范(下)
		JAVA编程规范(下) 2016-03-27 6. 代码的格式化 6.1 对代码进行格式化时,要达到的目的 1. 通过代码分割成功能块和便于理解的代码段,使代码更容易阅读和理解: 2. ... 
- JAVA 编程规范(上)
		2016-03-20 J120-CHARLIEPAN JAVA 编程规范(上) 1. 应用范围 本规范应用于采用J2EE规范的项目中,所有项目中的JAVA代码(含JSP,SERVLET,JA ... 
- 谷歌Java编程规范
		Google Java编程风格指南 January 20, 2014 作者:Hawstein 出处:http://hawstein.com/posts/google-java-style.html 声 ... 
- java注释规范
		前言: 现在java的出产地sun公司并没有定义一个java注释规范,注释规范目前是每个公司自己有自己的一套规范,主要是为了团队之间的协作. 1.基本规则 1.注释应该使代码更加清 ... 
随机推荐
- POJ.3145.Common Substrings(后缀数组 倍增 单调栈)
			题目链接 \(Description\) 求两个字符串长度不小于k的公共子串对数. \(Solution\) 求出ht[]后先减去k,这样对于两个后缀A',B',它们之间的贡献为min{ht(A)}( ... 
- android:定制 ListView 的界面
			只能显示一段文本的 ListView 实在是太单调了,我们现在就来对 ListView 的界面进行 定制,让它可以显示更加丰富的内容. 首先需要准备好一组图片,分别对应上面提供的每一种水果,待会我们要 ... 
- 奇怪吸引子---Hadley
			奇怪吸引子是混沌学的重要组成理论,用于演化过程的终极状态,具有如下特征:终极性.稳定性.吸引性.吸引子是一个数学概念,描写运动的收敛类型.它是指这样的一个集合,当时间趋于无穷大时,在任何一个有界集上出 ... 
- 微信小程序- 提示不在以下合法域名列表中
			第一次开发微信小程序时在访问后台数据时总是提示 提示上面问题主要有两个原因: 1.为配置安全合法域名列表: 微信小程序在开发时需要在官网配置固定的数据来源网站: 登录小程序平台中->设置: 图中 ... 
- MySql之插入操作
			一:插入一行数据 INSERT INTO tableName(列名...) VALUES(对应列名的值); 二:插入多行 INSERT INTO tableName(列名...) VALUES(对应列 ... 
- 阿里云服务器Centos7.4开放80端口的记录
			问题: 阿里云服务器安装的是centos7, 搭建网站安装lnmp1.5后发现访问不了, 不明所以, 在一论坛找到关于80端口未开放的原因. 需求: 开放80端口.于是有了下面第一,二,三部分关于开放 ... 
- cas 资源
			http://blog.sina.com.cn/s/blog_6fda308501012tk2.html http://www.blogjava.net/xmatthew/archive/2008/0 ... 
- 【RS】Sparse Probabilistic Matrix Factorization by Laplace Distribution for Collaborative Filtering -  基于拉普拉斯分布的稀疏概率矩阵分解协同过滤
			[论文标题]Sparse Probabilistic Matrix Factorization by Laplace Distribution for Collaborative Filtering ... 
- 【C#】详解C#序列化
			目录结构: contents structure [+] 简介 控制序列化和反序列化 特性(OnSerializing.OnSerialized.OnDeserializing.OnDeseriali ... 
- Vue(九):样式绑定v-bind示例
			Vue.js class class 与 style 是 HTML 元素的属性,用于设置元素的样式,我们可以用 v-bind 来设置样式属性. Vue.js v-bind 在处理 class 和 st ... 
