JMX 入门(二)
来源:互联网 发布:数据分析师职业规划 编辑:程序博客网 时间:2024/06/05 10:58
JMX 入门(二)
创建 JMX 客户端
前面一篇中,通过 MBeanServer
发布的 JMX 服务称之为服务端,我们已经知道如何通过 JConsole 作为客户端连接 JMX 服务,在这一篇中,我们将通过 Java 编码的方式来写客户端。
创建一个JMSClient
类,在类中创建 main
方法,然后开始下面的代码。
String host = "127.0.0.1";int port = 9999;String url = "service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/jmxrmi";JMXServiceURL serviceURL = new JMXServiceURL(url);final JMXConnector connector;try { connector = JMXConnectorFactory.connect(serviceURL);} catch (IOException e) { e.printStackTrace(); return;}MBeanServerConnection connection = connector.getMBeanServerConnection();
使用JMXConnectorFactory
方式连接时,JMXServiceURL
的参数 url
必须使用 service:jmx
方式进行连接,通过上面这种方式,我们得到了一个 JMX 客户端和服务器直接的连接 connection
。
遍历获取所有信息
下面,我们先通过遍历获取所有的 MBean
信息。
Set<ObjectName> objectNames = connection.queryNames(null, null);for (ObjectName objectName : objectNames) { System.out.println("========" + objectName + "========"); MBeanInfo mBeanInfo = connection.getMBeanInfo(objectName); System.out.println("[Attributes]"); for (MBeanAttributeInfo attr : mBeanInfo.getAttributes()) { Object value = null; try { value = attr.isReadable() ? connection.getAttribute(objectName, attr.getName()) : ""; } catch (Exception e) { value = e.getMessage(); } System.out.println(attr.getName() + ":" + value); } System.out.println("[Operations]"); for (MBeanOperationInfo oper : mBeanInfo.getOperations()) { System.out.println(oper.getName() + ":" + oper.getDescription()); } System.out.println("[Notifications]"); for (MBeanNotificationInfo notice : mBeanInfo.getNotifications()) { System.out.println(notice.getName() + ":" + notice.getDescription()); }}
首先通过 connection
的 queryNames
(方法参数为 null
时)获取所有的注册的 MBean
的名字,然后对名字进行遍历,根据名字获取 MBeanInfo
,在遍历获取其中的属性、操作和通知信息。在获取属性的时候,我们先判断属性是否可读,然后在通过 objectName
和属性名获取值。
我们先根据上一篇博客的内容,使用 9999 端口启动 JMX 服务(命令过长时,win 使用 ^
换行,linux 使用 \
换行):
java -Dcom.sun.management.jmxremote.port=9999 ^ -Dcom.sun.management.jmxremote.authenticate=false ^ -Dcom.sun.management.jmxremote.ssl=false ^ com.example.Main
编译运行 JMSClient
类,然后就能看到控制台输出了大量的信息,部分内容如下:
========java.lang:type=MemoryPool,name=Metaspace ========[属性信息]Name:MetaspaceType:NON_HEAPValid:trueCollectionUsage:nullCollectionUsageThreshold:java.lang.UnsupportedOperationException: CollectionUsage threshold is not supportedCollectionUsageThresholdCount:java.lang.UnsupportedOperationException: CollectionUsage threshold is not supportedMemoryManagerNames:[Ljava.lang.String;@7eda2dbbPeakUsage:javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=java.lang.management.MemoryUsage,items=((itemName=committed,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=init,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=max,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=used,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)))),contents={committed=10485760, init=0, max=-1, used=9806016})Usage:javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=java.lang.management.MemoryUsage,items=((itemName=committed,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=init,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=max,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)),(itemName=used,itemType=javax.management.openmbean.SimpleType(name=java.lang.Long)))),contents={committed=10485760, init=0, max=-1, used=9806016})UsageThreshold:0UsageThresholdCount:0CollectionUsageThresholdExceeded:java.lang.UnsupportedOperationException: CollectionUsage threshold is not supportedCollectionUsageThresholdSupported:falseUsageThresholdExceeded:falseUsageThresholdSupported:trueObjectName:java.lang:type=MemoryPool,name=Metaspace[操作信息]resetPeakUsage:resetPeakUsage[通知信息]========java.lang:type=MemoryPool,name=PS Old Gen ========[属性信息]Name:PS Old GenType:HEAPValid:true
上面日志中的大部分信息都是 JVM 相关的内容,当前程序的 JVM 信息可以通过 java.lang.management.ManagementFactory
工厂类获取。
从日志中找一下 com.example
的相关信息如下。
========com.example:type=Hello ========[属性信息]Name:ReginaldCacheSize:2006[操作信息]add:Operation exposed for managementsayHello:Operation exposed for management[通知信息]javax.management.AttributeChangeNotification:An attribute of this MBean has changed
获取指定的 MBean
通过上面遍历了解大概的信息后,我们以上面的创建 JMX 客户端为基础创建JMSClient2
。根据我们Main
中发布的对象名,我们这里手动创建相同的一个名字:
ObjectName objectName = new ObjectName("com.example:type=Hello");
然后使用 connection
通过指定名来进行其他操作,首先我们订阅当前对象的通知。
connection.addNotificationListener(objectName, new NotificationListener() { @Override public void handleNotification(Notification notification, Object handback) { System.out.println("\nReceived notification:"); System.out.println("\tClassName: " + notification.getClass().getName()); System.out.println("\tSource: " + notification.getSource()); System.out.println("\tType: " + notification.getType()); System.out.println("\tMessage: " + notification.getMessage()); if (notification instanceof AttributeChangeNotification) { AttributeChangeNotification acn = (AttributeChangeNotification) notification; System.out.println("\tAttributeName: " + acn.getAttributeName()); System.out.println("\tAttributeType: " + acn.getAttributeType()); System.out.println("\tNewValue: " + acn.getNewValue()); System.out.println("\tOldValue: " + acn.getOldValue()); } }}, null, null);
然后我们分别获取当前的值和修改当前的值,再调用提供的两个方法。
Object cacheSize = connection.getAttribute(objectName, "CacheSize");System.out.println("Get Value: " + cacheSize);connection.setAttribute(objectName, new Attribute("CacheSize", 100));connection.invoke(objectName, "sayHello", null, null);Object result = connection.invoke(objectName, "add", new Object[]{1, 9}, new String[]{int.class.getCanonicalName(), int.class.getCanonicalName()});System.out.println("1 + 9 = " + result);
编译执行 JMSClient2
,我们可以看到控制台输出的如下信息。
Get Value: 4519Received notification: ClassName: javax.management.AttributeChangeNotification Source: com.example:type=Hello Type: jmx.attribute.change Message: CacheSize changed AttributeName: CacheSize AttributeType: int NewValue: 100 OldValue: 45191 + 9 = 10
获取当前值后,又修改了值,我们收到一个值改变的通知,调用方法时可以看到服务端输出端的日志和客户端获得的结果。
使用 MBean 接口调用
在 JMSClient2
的基础上,如果我们当前可以得到 HelloMBean
接口,还可以像下面这样调用。
HelloMBean mbeanProxy = JMX.newMBeanProxy(connection, objectName, HelloMBean.class, true);System.out.println("Get Value: " + mbeanProxy.getCacheSize());mbeanProxy.setCacheSize(100);mbeanProxy.sayHello();int result = mbeanProxy.add(1, 9);System.out.println("1 + 9 = " + result);
这种方式和前面相比,调用更直接和简单,这里通过 JMX 创建动态代理,功能实现代码都在 MBeanServerInvocationHandler
类中,这个类根据调用的方法转换为 JMSClient2
中的方式进行调用,实现原理很简单(只要接口方法签名一致就能通过这种方式调用,不必是同一接口,和 Hessian的接口类似)。
这两种方式基本上就覆盖了 JMX 客户端的所有功能,类似 JConsole 的部分功能,实际上就是对 JMX 接口的调用和加工,通过 JMX 可以方便的监控资源和动态修改资源,还能在资源变化时使用通知提醒。这一篇的主要内容就是这些,可能会在下一篇中涉及SSL和用户密码登陆,还会使用一个很方便的 JMX 工具包。
代码下载
链接:http://pan.baidu.com/s/1skGR9Id 密码:mafm
- JMX 入门(二)
- JMX代码入门(二)
- JMX 入门(一)
- JMX 入门(三)
- JMX简介(二)
- JMX入门
- JMX入门
- jmx入门
- JMX入门
- JMX入门
- JMX入门
- JMX入门
- JMX入门
- JMX 入门
- JMX 入门
- JMX-入门
- 【JMX学习】1、jmx入门
- JMX规范(二):设备层
- python -day05
- Axure--使用阿里云搭建自己的原型发布站点
- JSON和JSONP的区别
- hdu6156 数位dp
- BFS/DFS 模板 代码
- JMX 入门(二)
- 3528:最小新整数
- HDU1251 统计难题【字典树】
- 乐观锁和悲观锁
- 基于FPGA的CORDIC算法实现——Verilog版
- 传递函数依赖
- Codeforces Round #411 D. Minimum number of steps (贪心。)
- Android(root)设备HTTPS请求时间校准
- Eclipse中安装Hibernate的插件