系列文章目录

Java管理扩展JMX入门学习
Spring JMX编程学习(一)- 手动注册bean到MBeanServer
Spring JMX编程学习(二)- 以Bean的方式注册MbeanServer
Spring JMX编程学习(三)- 自定义JMX客户端
Spring JMX编程学习(四)- MBeans自动探测与注解
Spring JMX编程学习(五)- SpringBoot自动注册


文章目录

  • 系列文章目录
  • 前言
  • 一、标准MBeans
    • 1. 创建MBean接口
    • 2. MBean实现类
    • 3. 创建一个JMX代理用于管理资源
    • 4. JConsole作为客户端管理
    • 5. 通知
  • 二、MXBeans
    • 1. 自定义数据类型
    • 2. 创建MXBean接口
    • 3. 创建MXBean实例
    • 4. 创建JMX代理管理资源
  • 三、远程连接与自定义JMX客户端
    • 1. 通过端口暴露程序用于远程管理
    • 2. 自定义JMX客户端管理程序
  • 总结

前言

Java管理扩展(JMX)(Java Management Extensions)技术是Java平台标准版(Java SE平台)的标准部分。JMX技术已在Java 2 Platform Standard Edition(J2SE)5.0版本中添加到该平台。

JMX技术提供了一种简单、标准的方法来管理资源,例如应用程序(applications),设备(devices)和服务(services)。由于JMX技术是动态的,因此可以在创建、安装和实施资源时使用它来监视和管理资源。您还可以使用JMX技术来监视和管理Java虚拟机(Java VM)。

JMX规范使用Java编程语言定义了体系结构,设计模式,API和服务,用于管理和监视应用程序和网络。

使用JMX技术,给定资源由一个或多个称为“Managed Beans”或MBean的Java对象检测。这些MBean在核心管理的对象服务器(称为MBean服务器)中注册。MBean服务器充当管理代理,并且可以在启用了Java编程语言的大多数设备上运行。

这些规范定义了用于管理已正确配置用于管理的任何资源的JMX代理。 JMX代理由其中注册了MBean的MBean服务器和用于处理MBean的一组服务组成。这样,JMX代理可以直接控制资源,并使资源可用于远程管理应用程序。

检测资源的方式完全独立于管理基础架构。因此,无论如何实现其管理应用程序,都可以使资源变得可管理。

JMX技术定义了标准连接器(称为JMX连接器 JMX connectors),使您可以从远程管理应用程序访问JMX代理。使用不同协议的JMX连接器提供相同的管理接口。因此,无论使用何种通信协议,管理应用程序都可以透明地管理资源。不符合JMX规范的系统或应用程序也可以使用JMX代理,只要这些系统或应用程序支持JMX代理即可。


提示:以下是本篇文章正文内容,下面案例可供参考

一、标准MBeans

1. 创建MBean接口

package com.example.jmx;/*** By convention, an MBean interface takes the name of the Java class that implements it,* with the suffix MBean added*/
public interface HelloMBean {// declares two operations: the Java methods add() and sayHello()void sayHello();int add(int x, int y);// two attributes: Name is a read-only string, and CacheSize is an integer that can be both read and writtenString getName();int getCacheSize();void setCacheSize(int size);
}

2. MBean实现类

package com.example.jmx;public class Hello implements HelloMBean {private static final intDEFAULT_CACHE_SIZE = 200;private final String name = "Reginald";private int cacheSize = DEFAULT_CACHE_SIZE;@Overridepublic void sayHello() {System.out.println("hello, world");}@Overridepublic int add(int x, int y) {return x + y;}@Overridepublic String getName() {return this.name;}@Overridepublic int getCacheSize() {return this.cacheSize;}@Overridepublic synchronized void setCacheSize(int size) {this.cacheSize = size;System.out.println("Cache size now " + this.cacheSize);}
}

3. 创建一个JMX代理用于管理资源

package com.example.jmx;import javax.management.MBeanServer;
import javax.management.ObjectName;
import java.lang.management.ManagementFactory;public class Main {public static void main(String[] args) throws Exception {// obtaining an MBean server created and initialized by the platform//  If no MBean server has been created by the platform already, then getPlatformMBeanServer() creates an MBean//  server automatically by calling the JMX method MBeanServerFactory.createMBeanServer()MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();// 每个Mbean都必须包含ObjectNameObjectName name = new ObjectName("com.example.jmx:type=Hello");Hello mbean = new Hello();mbs.registerMBean(mbean, name);System.out.println("Waiting forever...");Thread.sleep(Long.MAX_VALUE);}
}

在以上的main方法当中,通过java.lang.management.ManagementFactory#getPlatformMBeanServer方法获取一个已经创建和初始化的MBean server,如果当前平台还没有创建的话,该方法会自动调用javax.management.MBeanServerFactory#createMBeanServer方法创建一个。并同时注册一些JDK中自带的MXBeans,比如java.lang.management.MemoryPoolMXBeanjava.lang.management.MemoryManagerMXBean.创建MBeanServer之后,定义了一个MBean实例,每个MBean实例必须包含一个ObjectName,这个对象的值必须按照JMX的标准来定义,比如上面的com.example.jmx:type=Hello就包含包名、双引号、type、等号和MBean的名称。然后创建一个mbean对象,并通过javax.management.MBeanServer#registerMBean方法注册到MBeanServer当中。

private static MBeanServer platformMBeanServer;public static synchronized MBeanServer getPlatformMBeanServer() {SecurityManager sm = System.getSecurityManager();if (sm != null) {Permission perm = new MBeanServerPermission("createMBeanServer");sm.checkPermission(perm);}// 如果platformMBeanServer还不存在 就会创建一个if (platformMBeanServer == null) {platformMBeanServer = MBeanServerFactory.createMBeanServer();// 自动注册一些平台的MXBeans 比如MemoryPoolMXBean和MemoryManagerMXBeanfor (PlatformComponent pc : PlatformComponent.values()) {List<? extends PlatformManagedObject> list =pc.getMXBeans(pc.getMXBeanInterface());for (PlatformManagedObject o : list) {// Each PlatformComponent represents one management// interface. Some MXBean may extend another one.// The MXBean instances for one platform component// (returned by pc.getMXBeans()) might be also// the MXBean instances for another platform component.// e.g. com.sun.management.GarbageCollectorMXBean//// So need to check if an MXBean instance is registered// before registering into the platform MBeanServerif (!platformMBeanServer.isRegistered(o.getObjectName())) {addMXBean(platformMBeanServer, o);}}}HashMap<ObjectName, DynamicMBean> dynmbeans =ManagementFactoryHelper.getPlatformDynamicMBeans();for (Map.Entry<ObjectName, DynamicMBean> e : dynmbeans.entrySet()) {addDynamicMBean(platformMBeanServer, e.getValue(), e.getKey());}for (final PlatformManagedObject o :ExtendedPlatformComponent.getMXBeans()) {if (!platformMBeanServer.isRegistered(o.getObjectName())) {addMXBean(platformMBeanServer, o);}}}// 已经存在 则直接返回return platformMBeanServer;
}

4. JConsole作为客户端管理

在jdk的bin目录下查找到jconsole小工具,然后打开

选择到自己的进程,并点击下面的连接,连接过程提示安全问题,可以忽略,选用不安全的连接.



这个jConsol也称为监视和管理控制台,工具栏中包含有一些内存线程这些信息,其实都是通过JMX技术从服务端获取的(系统默认注册)。我们现在看mBean这个选项。很容易就会发现我们自己注册的mBean(com.example.jmx.Hello)。在mBeanInfo当中我们可以看到ObjectNameClassName信息,另外在描述符里面也有interfaceClassName这些信息。

在左侧我们可以看到这个mBean的属性和操作,其实在定义mBean接口的时候,我们通过setter/getter方法来定义属性(Attributes),如果只有getter方法,这个属性就是只读的,包含setter/getter方法才是可写可读,如果不是setter/getter方法那么就属于操作(Operations)。比如上面的add和sayHello。
对于属性cacheSize,就是可读可写的,当前的值为200.

尝试修改这个属性,被监视和管理的程序内存值就被改变了。

Name这个属性是不可写入的,因为com.example.jmx.HelloMBean接口中没有提供setter方法。

接下来我们再看一下操作,通过jConsole来执行一下操作。

5. 通知

JMX API定义了一种机制,使MBean能够生成通知,例如,以信号通知状态更改,检测到的事件或问题。

要生成通知,MBean必须实现接口NotificationEmitter或扩展NotificationBroadcasterSupport。 要发送通知,您需要构造类javax.management.Notification的实例或子类(例如AttributeChangedNotification),然后将该实例传递给NotificationBroadcasterSupport.sendNotification。

每个通知都有一个来源。 源是生成通知的MBean的对象名称。

每个通知都有一个序列号。 当订单很重要时,此数字可用于订购来自同一来源的通知,并且存在以错误的顺序处理通知的风险。 序列号可以为零,但是对于给定MBean的每个通知,序列号最好递增。

修改MBean定义

package com.example.jmx;import javax.management.AttributeChangeNotification;
import javax.management.MBeanNotificationInfo;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;public class Helloextends NotificationBroadcasterSupport implements HelloMBean {private static final int DEFAULT_CACHE_SIZE = 200;private final String name = "Reginald";private int cacheSize = DEFAULT_CACHE_SIZE;private long sequenceNumber = 1;@Overridepublic void sayHello() {System.out.println("hello, world");}@Overridepublic int add(int x, int y) {return x + y;}/* Getter for the Name attribute. The pattern shown here is frequent: thegetter returns a private field representing the attribute value. In ourcase, the attribute value never changes, but for other attributes itmight change as the application runs. Consider an attribute representingstatistics such as uptime or memory usage, for example. Being read-onlyjust means that it can't be changed through the management interface. */@Overridepublic String getName() {return this.name;}/* Getter for the CacheSize attribute. The pattern shown here isfrequent: the getter returns a private field representing theattribute value, and the setter changes that field. */@Overridepublic int getCacheSize() {return this.cacheSize;}/* Setter for the CacheSize attribute. To avoid problems withstale values in multithreaded situations, it is a good ideafor setters to be synchronized. */@Overridepublic synchronized void setCacheSize(int size) {int oldSize = this.cacheSize;this.cacheSize = size;/* In a real application, changing the attribute wouldtypically have effects beyond just modifying the cacheSizefield.  For example, resizing the cache might meandiscarding entries or allocating new ones. The logic forthese effects would be here. */System.out.println("Cache size now " + this.cacheSize);/* Construct a notification that describes the change. The"source" of a notification is the ObjectName of the MBeanthat emitted it. But an MBean can put a reference toitself ("this") in the source, and the MBean server willreplace this with the ObjectName before sending thenotification on to its clients.For good measure, we maintain a sequence number for eachnotification emitted by this MBean.The oldValue and newValue parameters to the constructor areof type Object, so we are relying on Tiger's autoboxinghere.  */Notification n =new AttributeChangeNotification(this,sequenceNumber++,System.currentTimeMillis(),"CacheSize changed","CacheSize","int",oldSize,this.cacheSize);/* Now send the notification using the sendNotification methodinherited from the parent class NotificationBroadcasterSupport. */sendNotification(n);}@Overridepublic 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};}
}

以上AttributeChangeNotification参数:

重启通过JConsole连接

点击订阅

在com.example.jmx.Hello#setCacheSize方法中会发送通知(sendNotification),因为修改属性

通过以上的小案例,我们展示了MBeans的使用。总结一下:

MBean是类似于JavaBeans组件的托管Java对象,它遵循JMX规范中阐述的设计模式。 MBean可以代表设备,应用程序或任何需要管理的资源。 MBean公开了一个包含以下内容的管理接口:

  • 一组可读或可写的属性,或两者兼而有之。
  • 一组可调用的操作。
  • 自我描述。

在MBean实例的整个生命周期中,管理界面都不会更改。 当某些预定义事件发生时,MBeans也可以发出通知。

二、MXBeans

MXBean是一种MBean,仅引用一组预定义的数据类型。 这样,您可以确保您的MBean可被任何客户端(包括远程客户端)使用,而无需客户端有权访问代表MBeans类型的特定于模型的类。 MXBean提供了一种方便的方式将相关值捆绑在一起,而无需将客户端进行特殊配置以处理捆绑。

以与标准MBean相同的方式,通过编写称为SomethingMXBean的Java接口和实现该接口的Java类来定义MXBean。 但是,与标准MBean不同,MXBean不需要将Java类称为Something。 接口中的每个方法都定义MXBean中的属性或操作。 注释@MXBean也可以用于注释Java接口,而不是要求接口名称后跟MXBean后缀。

1. 自定义数据类型

创建一个自定义的数据类型:

/** QueueSample.java - Java type representing a snapshot of a given queue.* It bundles together the instant time the snapshot was taken, the queue* size and the queue head.*/package com.example.mxb;import java.beans.ConstructorProperties;
import java.util.Date;public class QueueSample {private final Date date;private final int size;private final String head;/*** convert the given instance into a CompositeData instance and uses the @ConstructorProperties annotation to* reconstruct a QueueSample instance from a CompositeData instance*/@ConstructorProperties({"date", "size", "head"})public QueueSample(Date date, int size, String head) {this.date = date;this.size = size;this.head = head;}public Date getDate() {return date;}public int getSize() {return size;}public String getHead() {return head;}
}

2. 创建MXBean接口

创建一个MXBean接口:

package com.example.mxb;public interface QueueMXBean {public QueueSample getQueueSample();public void clearQueue();
}

3. 创建MXBean实例

创建一个MXBean实例,注意这里的实例不需要名称为Queue(接口名称除去MXBean部分),可以是任意其他名字,此处使用QueueSampler

package com.example.mxb;import java.util.Date;
import java.util.Queue;public class QueueSampler implements QueueMXBean {private Queue<String> queue;public QueueSampler(Queue<String> queue) {this.queue = queue;}@Overridepublic QueueSample getQueueSample() {synchronized (queue) {return new QueueSample(new Date(), queue.size(), queue.peek());}}@Overridepublic void clearQueue() {synchronized (queue) {queue.clear();}}
}

4. 创建JMX代理管理资源

代码如下(与MBean注册方式是一模一样的):

package com.example.mxb;import javax.management.MBeanServer;
import javax.management.ObjectName;
import java.lang.management.ManagementFactory;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;public class Main {/* For simplicity, we declare "throws Exception".Real programs will usually want finer-grained exception handling. */public static void main(String[] args) throws Exception {// Get the Platform MBean ServerMBeanServer mbs = ManagementFactory.getPlatformMBeanServer();// Construct the ObjectName for the QueueSampler MXBean we will registerObjectName mxbeanName = new ObjectName("com.example.mxb:type=QueueSampler");// Create the Queue Sampler MXBeanQueue<String> queue = new ArrayBlockingQueue<String>(10);queue.add("Request-1");queue.add("Request-2");queue.add("Request-3");QueueSampler mxbean = new QueueSampler(queue);// Register the Queue Sampler MXBeanmbs.registerMBean(mxbean, mxbeanName);// Wait foreverSystem.out.println("Waiting for incoming requests...");Thread.sleep(Long.MAX_VALUE);}
}

运行main程序,通过Jconsole查看

  • 查看属性



可以点击刷新按钮获取最新的值

  • 查看操作


原来队列中是有三个元素的,在清空队列之后,再去查看

总结一下,MXBean的操作和MBean其实是差不多的,就是在规范方面不同而已,比如实例名称与接口不需要硬性符合某种关系,另外可以使用自己定义的数据接口传输属性。


三、远程连接与自定义JMX客户端

1. 通过端口暴露程序用于远程管理

JMX技术允许我们通过JMX connectors进行远程管理,在上面的几个案例当中其实JConsole和被管理的程序使用的其实是一个JVM实例。如果是远程管理,应该是属于不同的JVM实例。

JMX连接器使MBean服务器可供基于Java技术的远程客户端访问。连接器的客户端导出与MBean服务器基本相同的接口。

JMX连接器由连接器客户端和连接器服务器组成。连接器服务器连接到MBean服务器,并侦听来自客户端的连接请求。连接器客户端负责与连接器服务器建立连接。连接器客户端通常与连接器服务器位于不同的Java虚拟机(Java VM)中,并且通常在不同的计算机上运行。 JMX API定义了基于远程方法调用(RMI)的标准连接协议。使用此协议,您可以将JMX客户端从远程位置连接到MBean服务器中的MBean,并在MBean上执行操作,就像在本地执行操作一样。

Java SE平台提供了一种开箱即用的方法,可以使用JMX API的标准RMI连接器来远程监视应用程序。开箱即用的RMI连接器自动公开用于远程管理的应用程序,而无需您自己创建专用的远程连接器服务器。通过使用正确的属性启动Java应用程序来激活即用型远程管理代理。然后,与JMX技术兼容的监视和管理应用程序可以连接到这些应用程序并进行远程监视。

首先将以上两个小程序合并到一起,使用一个主程序启动

/** Main.java - main class for the Hello MBean and QueueSampler MXBean example.* Create the Hello MBean and QueueSampler MXBean, register them in the platform* MBean server, then wait forever (or until the program is interrupted).*/package com.example.notify;import javax.management.MBeanServer;
import javax.management.ObjectName;
import java.lang.management.ManagementFactory;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;public class Main {/* For simplicity, we declare "throws Exception".Real programs will usually want finer-grained exception handling. */public static void main(String[] args) throws Exception {// Get the Platform MBean ServerMBeanServer mbs = ManagementFactory.getPlatformMBeanServer();// Construct the ObjectName for the Hello MBean we will registerObjectName mbeanName = new ObjectName("com.example.notify:type=Hello");// Create the Hello World MBeanHello mbean = new Hello();// Register the Hello World MBeanmbs.registerMBean(mbean, mbeanName);// Construct the ObjectName for the QueueSampler MXBean we will registerObjectName mxbeanName = new ObjectName("com.example.notify:type=QueueSampler");// Create the Queue Sampler MXBeanQueue<String> queue = new ArrayBlockingQueue<String>(10);queue.add("Request-1");queue.add("Request-2");queue.add("Request-3");QueueSampler mxbean = new QueueSampler(queue);// Register the Queue Sampler MXBeanmbs.registerMBean(mxbean, mxbeanName);// Wait foreverSystem.out.println("Waiting for incoming requests...");Thread.sleep(Long.MAX_VALUE);}
}

并通过以下方式运行主程序(模拟远程端口为9999)

java -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false com.example.notify.Main

注意需要在项目根目录运行

当然也可以通过IDE设置系统参数的方式(比如IDEA当中)

启动完成之后,通过JConsole远程连接

2. 自定义JMX客户端管理程序

本教程的先前课程向您展示了如何创建JMX技术MBean和MXBean,以及如何向JMX代理注册它们。 但是,所有前面的示例都使用了现有的JMX客户端JConsole。 本课将演示如何创建自己的自定义JMX客户端。

package com.example.notify;import javax.management.*;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.io.IOException;
import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;public class Client {/* For simplicity, we declare "throws Exception".Real programs will usually want finer-grained exception handling. */public static void main(String[] args) throws Exception {// Create an RMI connector client and// connect it to the RMI connector server//

首先通过javax.management.remote.JMXConnectorFactory#connect工厂方法获取一个JMXConnector对象。创建这个对象主要是用于创建一个MBeanServerConnection.

        echo("\nCreate an RMI connector client and " +"connect it to the RMI connector server");// 前提是开启MBeanXServer java -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false com.example.notify.MainJMXServiceURL url =new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:9999/jmxrmi");JMXConnector jmxc = JMXConnectorFactory.connect(url, null);// Get an MBeanServerConnection// 获取连接echo("\nGet an MBeanServerConnection");MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();waitForEnterPressed();

获取连接之后,就可以获取到已经注册的MBean了,方法为javax.management.MBeanServerConnection#getDomains。还有其他的一些有用接口getDefaultDomain、getMBeanCount等。

        // Get domains from MBeanServer//echo("\nDomains:");String domains[] = mbsc.getDomains();Arrays.sort(domains);for (String domain : domains) {echo("\tDomain = " + domain);}waitForEnterPressed();// Get MBeanServer's default domain//echo("\nMBeanServer default domain = " + mbsc.getDefaultDomain());// Get MBean count//echo("\nMBean count = " + mbsc.getMBeanCount());// Query MBean names//echo("\nQuery MBeanServer MBeans:");Set<ObjectName> names =new TreeSet<ObjectName>(mbsc.queryNames(null, null));for (ObjectName name : names) {echo("\tObjectName = " + name);}waitForEnterPressed();

以上代码运行结果如下

Create an RMI connector client and connect it to the RMI connector serverGet an MBeanServerConnectionPress <Enter> to continue...Domains:Domain = JMImplementationDomain = com.example.notifyDomain = com.sun.managementDomain = java.langDomain = java.nioDomain = java.util.loggingPress <Enter> to continue...MBeanServer default domain = DefaultDomainMBean count = 24Query MBeanServer MBeans:ObjectName = JMImplementation:type=MBeanServerDelegateObjectName = com.example.notify:type=HelloObjectName = com.example.notify:type=QueueSamplerObjectName = com.sun.management:type=DiagnosticCommandObjectName = com.sun.management:type=HotSpotDiagnosticObjectName = java.lang:type=ClassLoadingObjectName = java.lang:type=CompilationObjectName = java.lang:type=GarbageCollector,name=PS MarkSweepObjectName = java.lang:type=GarbageCollector,name=PS ScavengeObjectName = java.lang:type=MemoryObjectName = java.lang:type=MemoryManager,name=CodeCacheManagerObjectName = java.lang:type=MemoryManager,name=Metaspace ManagerObjectName = java.lang:type=MemoryPool,name=Code CacheObjectName = java.lang:type=MemoryPool,name=Compressed Class SpaceObjectName = java.lang:type=MemoryPool,name=MetaspaceObjectName = java.lang:type=MemoryPool,name=PS Eden SpaceObjectName = java.lang:type=MemoryPool,name=PS Old GenObjectName = java.lang:type=MemoryPool,name=PS Survivor SpaceObjectName = java.lang:type=OperatingSystemObjectName = java.lang:type=RuntimeObjectName = java.lang:type=ThreadingObjectName = java.nio:type=BufferPool,name=directObjectName = java.nio:type=BufferPool,name=mappedObjectName = java.util.logging:type=LoggingPress <Enter> to continue...

其中就包含我们创建的
Domain = com.example.notify和ObjectName = com.example.notify:type=Hello、ObjectName = com.example.notify:type=QueueSampler,接下来我们在客户端通过创建Mbean的代理(javax.management.JMX#newMBeanProxy(javax.management.MBeanServerConnection, javax.management.ObjectName, java.lang.Class<T>, boolean))、监听然后修改属性。

        // ----------------------// Manage the Hello MBean// ----------------------echo("\n>>> Perform operations on Hello MBean <<<");// Construct the ObjectName for the Hello MBean//ObjectName mbeanName = new ObjectName("com.example.notify:type=Hello");// Create a dedicated proxy for the MBean instead of// going directly through the MBean server connection// 创建一个远程代理HelloMBean mbeanProxy =JMX.newMBeanProxy(mbsc, mbeanName, HelloMBean.class, true);// Add notification listener on Hello MBean//echo("\nAdd notification listener...");// Create listener// 创建一个监听器 所谓的订阅ClientListener listener = new ClientListener();mbsc.addNotificationListener(mbeanName, listener, null, null);// Get CacheSize attribute in Hello MBean// 获取值echo("\nCacheSize = " + mbeanProxy.getCacheSize());// Set CacheSize attribute in Hello MBean// Calling "reset" makes the Hello MBean emit a// notification that will be received by the registered// ClientListener.// 设置值mbeanProxy.setCacheSize(150);// Sleep for 2 seconds to have time to receive the notification//echo("\nWaiting for notification...");sleep(2000);// Get CacheSize attribute in Hello MBean//echo("\nCacheSize = " + mbeanProxy.getCacheSize());// Invoke "sayHello" in Hello MBean//echo("\nInvoke sayHello() in Hello MBean...");mbeanProxy.sayHello();// Invoke "add" in Hello MBean//echo("\nInvoke add(2, 3) in Hello MBean...");echo("\nadd(2, 3) = " + mbeanProxy.add(2, 3));waitForEnterPressed();// ------------------------------// Manage the QueueSampler MXBean// ------------------------------echo("\n>>> Perform operations on QueueSampler MXBean <<<");// Construct the ObjectName for the QueueSampler MXBean//ObjectName mxbeanName =new ObjectName("com.example.notify:type=QueueSampler");// Create a dedicated proxy for the MXBean instead of// going directly through the MBean server connection//QueueSamplerMXBean mxbeanProxy =JMX.newMXBeanProxy(mbsc, mxbeanName, QueueSamplerMXBean.class);// Get QueueSample attribute in QueueSampler MXBean//QueueSample queue1 = mxbeanProxy.getQueueSample();echo("\nQueueSample.Date = " + queue1.getDate());echo("QueueSample.Head = " + queue1.getHead());echo("QueueSample.Size = " + queue1.getSize());// Invoke "clearQueue" in QueueSampler MXBean//echo("\nInvoke clearQueue() in QueueSampler MXBean...");mxbeanProxy.clearQueue();// Get QueueSample attribute in QueueSampler MXBean//QueueSample queue2 = mxbeanProxy.getQueueSample();echo("\nQueueSample.Date = " + queue2.getDate());echo("QueueSample.Head = " + queue2.getHead());echo("QueueSample.Size = " + queue2.getSize());waitForEnterPressed();// Close MBeanServer connection// 关闭连接echo("\nClose the connection to the server");jmxc.close();echo("\nBye! Bye!");}private static void echo(String msg) {System.out.println(msg);}private static void sleep(int millis) {try {Thread.sleep(millis);} catch (InterruptedException e) {e.printStackTrace();}}private static void waitForEnterPressed() {try {echo("\nPress <Enter> to continue...");System.in.read();} catch (IOException e) {e.printStackTrace();}}/*** Inner class that will handle the notifications.*/public static class ClientListener implements NotificationListener {@Overridepublic void handleNotification(Notification notification,Object handback) {echo("\nReceived notification:");echo("\tClassName: " + notification.getClass().getName());echo("\tSource: " + notification.getSource());echo("\tType: " + notification.getType());echo("\tMessage: " + notification.getMessage());if (notification instanceof AttributeChangeNotification) {AttributeChangeNotification acn =(AttributeChangeNotification) notification;echo("\tAttributeName: " + acn.getAttributeName());echo("\tAttributeType: " + acn.getAttributeType());echo("\tNewValue: " + acn.getNewValue());echo("\tOldValue: " + acn.getOldValue());}}}
}

执行结果如下

>>> Perform operations on Hello MBean <<<Add notification listener...CacheSize = 200Waiting for notification...Received notification:ClassName: javax.management.AttributeChangeNotificationSource: com.example.notify:type=HelloType: jmx.attribute.changeMessage: CacheSize changedAttributeName: CacheSizeAttributeType: intNewValue: 150OldValue: 200CacheSize = 150Invoke sayHello() in Hello MBean...Invoke add(2, 3) in Hello MBean...add(2, 3) = 5Press <Enter> to continue...>>> Perform operations on QueueSampler MXBean <<<QueueSample.Date = Thu Nov 19 14:34:02 CST 2020
QueueSample.Head = Request-1
QueueSample.Size = 3Invoke clearQueue() in QueueSampler MXBean...QueueSample.Date = Thu Nov 19 14:34:02 CST 2020
QueueSample.Head = null
QueueSample.Size = 0Press <Enter> to continue...Close the connection to the serverBye! Bye!Process finished with exit code 0

总结

以上案例来自官方教程实例:https://docs.oracle.com/javase/tutorial/jmx/TOC.html

Java管理扩展JMX入门学习相关推荐

  1. 01_Weblogic课程之概念篇:代理服务器,web服务器,应用程序服务器,JNDI概念,JTA概念,Java消息服务,Java验证和授权(JAAS),Java管理扩展,Web客户机,客户机应用程序

     1 什么是服务器 Weblogic中服务器分为两种,一种是受管服务器,另外一种是管理服务器. Weblogic课程(Weblogic是Oracle公司的,最开始的是BEA公司的) 一 系统管理 ...

  2. sts java配置tomcat_Java Web入门学习(一) STS与Tomcat配置

    Java Web学习(一) STS与Tomcat配置 一.IDE的选择 使用基于Eclipse的STS Ide ,个人感觉挺好用的. 根据以上两张图片,将STS 下载下来.然后解压缩. 用编辑器打开S ...

  3. Java管理扩展指南之MBean简介

    MBean简介 1.1. MBeans简要介绍 本课程介绍JMX API的基本概念,它被称之为被管理的bean,或者MBean. MBean是一个被管理的Java对象,就像Javabean组件一样,但 ...

  4. 从黑箱到企业: 管理,JMX 1.1 样式

    [IT168 技术文章]在本文中研究了网络管理软件的历史,以及它是如何从开始阶段粗陋的软件发展成现今这样复杂而成熟的企业管理系统的.他还研究了困扰这些系统的许多常见问题的根源.以及如何利用 JMX 来 ...

  5. JMX 入门(一)基础操作

    JMX 官方教程:http://docs.oracle.com/javase/tutorial/jmx/index.html 这篇博客参考官方教程以及个人的理解,通过实际的代码和操作来学会使用 JMX ...

  6. java 监控之JMX规范1

    1.  JMX规范 JMX是"Java管理扩展的"的缩写,它和其他JavaEE类似也是曾经的Sun提出的一种规范(规约),从名字上可以看出主要是负责系统管理.是一个为系统加入或者说 ...

  7. java -jar 默认参数_JAVA入门学习指南,建议收藏

    如果你不懂Java 并且想认真学习接触了解一下Java的语法,建议把这篇文章收藏了,多看几遍,应该可以初步掌握Java 大部分基础的语法 . 让我们出发吧!ps:本文有点长,耐心阅读 . 〇,编程环境 ...

  8. Java入门学习注意事项有哪些?

    想要学好java技术,做好学习规划路线和注意事项是非常重要的,尤其是零基础学员,Java涉及到的知识点非常多,我们需要制定合理的Java学习路线图,这样会事半功倍,下面小编和大家总结一下Java入门学 ...

  9. Java入门学习笔记[狂神说Java]

    写在前面: 本文根据B站狂神说Java 与菜鸟教程 整理而来,仅供个人学习使用,如有侵权,请联系删除. 文章目录 IDEA使用 Java基础01:注释 Java基础02:数据类型 Java基础03:类 ...

最新文章

  1. python二元函数求导_用Excel和python实现二元函数梯度下降的人工智能,之用,excel,一元...
  2. 35张图,看懂肠道和大脑的魔性关系,绝对涨知识!
  3. php微信墙开发,Node.js如何开发微信墙
  4. 【网址收藏】IDEA社区版(Community)和付费版(UItimate)的区别
  5. 博士申请 | 香港科技大学谢知遥教授实验组招收机器学习全奖博士生
  6. PCB设计过孔选用指导
  7. Shell 变量及函数讲解 [2]
  8. jQuery初识 - jQuery中的方法
  9. 你想知道的动态URL、静态URl、伪静态URL概念及区别都在这里!
  10. HDU2892 area 简单多边形与圆面积交
  11. la是什么牌子_La Prairie
  12. TortoiseSVN的安装和使用
  13. 腾讯数据库专家多年运维经验凝聚成简,总结这份595页工作笔记
  14. kernel panic 分析解决方法
  15. Android studio毕设制作液体动画Animation(毕业设计2048小游戏)
  16. win10升级助手_Win10系统易升如何彻底关闭?「系统天地」
  17. ESP32-IDF开发实例-ADC电压采集
  18. 跳妹儿学编程之ScratchJr(五):ScratchJr入门程序积木块功能介绍与使用技巧
  19. 计算机系统时间无法更改,Win7电脑无法修改系统时间如何解决?
  20. VR乒乓球项目Unity3D 开发经验整理,4简单而有效的AI

热门文章

  1. 从ARM9到A15 手机处理器架构进化历程
  2. android仿微信界面的实现
  3. 中国银行的海外IT建设之路
  4. 【竞赛篇-新苗申报立项】浙江省新苗人才计划申报经验
  5. 支付宝支付开发——当面付条码支付和扫码支付
  6. 微电子系统封装期末总结—国科大集成电路学院
  7. 期末大作业纯前端技术实现个人简历模板
  8. Win10屏幕亮度调节失效之终极解决方案
  9. 一个JavaScript写的黑白棋AI
  10. 突发 2022大陆多地AP考试积取消 究竟该如何应对?