Java教程是针对JDK 8编写的。本页面描述的示例和实践未利用后续版本中引入的改进,并且可能使用不再可用的技术。
有关Java SE 9及其后续版本中更新的语言特性的摘要,请参阅Java语言更改。
有关所有JDK版本的新功能、增强功能和已删除或弃用选项的信息,请参阅JDK发行说明。
在此教程中,之前的课程已经向您展示了如何创建JMX技术的MBeans和MXBeans,并将它们注册到JMX代理中。然而,之前的所有示例都使用了现有的JMX客户端JConsole。本课程将演示如何创建您自己的自定义JMX客户端。
自定义JMX客户端的一个示例,Client
,包含在jmx_examples.zip
中。该JMX客户端与之前课程中看到的相同的MBean、MXBean和JMX代理进行交互。由于Client
类的大小,它将在以下部分中分块进行检查。
要能够从JMX客户端创建到远程运行的JMX代理的连接,您需要使用javax.management.remote
包中的类。
package com.example; ... import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL; public class Client { ...
Client
类将创建JMXConnector
实例,为此它将需要一个JMXConnectorFactory
和一个JMXServiceURL
。
JMX客户端需要一个通知处理程序,用于监听和处理可能由注册在JMX代理的MBean服务器中的MBeans发送的任何通知。JMX客户端的通知处理程序是NotificationListener
接口的一个实例,如下所示。
... public static class ClientListener implements NotificationListener { public void handleNotification(Notification notification, Object handback) { echo("\n收到通知:"); echo("\t类名: " + notification.getClass().getName()); echo("\t源: " + notification.getSource()); echo("\t类型: " + notification.getType()); echo("\t消息: " + notification.getMessage()); if (notification instanceof AttributeChangeNotification) { AttributeChangeNotification acn = (AttributeChangeNotification) notification; echo("\t属性名称: " + acn.getAttributeName()); echo("\t属性类型: " + acn.getAttributeType()); echo("\t新值: " + acn.getNewValue()); echo("\t旧值: " + acn.getOldValue()); } } } ...
此通知侦听器确定接收到的任何通知的来源,并检索存储在通知中的信息。然后,根据接收到的通知类型,它会对通知信息执行不同的操作。在本例中,当侦听器接收到AttributeChangeNotification
类型的通知时,它将通过调用AttributeChangeNotification
的getAttributeName
、getAttributeType
、getNewValue
和getOldValue
方法获取已更改的MBean属性的名称、类型以及其旧值和新值。
稍后在代码中创建了一个新的ClientListener
实例。
ClientListener listener = new ClientListener();
Client
类创建一个RMI连接器客户端,该客户端配置为连接到RMI连接器服务器。在启动JMX代理Main
时,将启动该服务器。这将使JMX客户端能够与JMX代理进行交互,就像它们在同一台计算机上运行一样。
... public static void main(String[] args) throws Exception { echo("\n创建一个RMI连接器客户端并将其连接到RMI连接器服务器"); JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:9999/jmxrmi"); JMXConnector jmxc = JMXConnectorFactory.connect(url, null); ...
如您所见,Client
定义了一个名为url
的JMXServiceURL
,它表示连接器客户端期望找到连接器服务器的位置。此URL允许连接器客户端从本地主机的端口9999上运行的RMI注册表中检索到RMI连接器服务器存根jmxrmi
,并连接到RMI连接器服务器。
通过标识RMI注册表,可以创建连接器客户端。连接器客户端jmxc
是由JMXConnectorFactory
的connect()
方法创建的JMXConnector
接口的实例。调用connect()
方法时,传递了url
参数和一个空环境映射。
建立RMI连接后,JMX客户端必须连接到远程MBean服务器,以便能够与远程JMX代理注册的各种MBean进行交互。
... MBeanServerConnection mbsc = jmxc.getMBeanServerConnection(); ...
通过调用JMXConnector
实例jmxc
的getMBeanServerConnection()
方法创建了一个名为mbsc的MBeanServerConnection
实例。
连接器客户端现在已连接到由JMX代理创建的MBean服务器,并且可以在连接的两端完全透明地注册MBean并对其执行操作。
首先,客户端定义了一些简单的操作来获取有关代理MBean服务器中找到的MBean的信息。
... echo("\nDomains:"); String domains[] = mbsc.getDomains(); Arrays.sort(domains); for (String domain : domains) { echo("\tDomain = " + domain); } ... echo("\nMBeanServer default domain = " + mbsc.getDefaultDomain()); echo("\nMBean count = " + mbsc.getMBeanCount()); echo("\nQuery MBeanServer MBeans:"); Set<ObjectName> names = new TreeSet<ObjectName>(mbsc.queryNames(null, null)); for (ObjectName name : names) { echo("\tObjectName = " + name); } ...
客户端调用MBeanServerConnection
的各种方法,以获取不同MBean所在的域,注册在MBean服务器中的MBean的数量以及它所发现的每个MBean的对象名称。
客户端通过MBean服务器连接访问MBean服务器中的Hello
MBean,通过创建MBean代理。这个MBean代理是客户端本地的,并模拟远程MBean。
... ObjectName mbeanName = new ObjectName("com.example:type=Hello"); HelloMBean mbeanProxy = JMX.newMBeanProxy(mbsc, mbeanName, HelloMBean.class, true); echo("\nAdd notification listener..."); mbsc.addNotificationListener(mbeanName, listener, null, null); echo("\nCacheSize = " + mbeanProxy.getCacheSize()); mbeanProxy.setCacheSize(150); echo("\nWaiting for notification..."); sleep(2000); echo("\nCacheSize = " + mbeanProxy.getCacheSize()); echo("\nInvoke sayHello() in Hello MBean..."); mbeanProxy.sayHello(); echo("\nInvoke add(2, 3) in Hello MBean..."); echo("\nadd(2, 3) = " + mbeanProxy.add(2, 3)); waitForEnterPressed(); ...
MBean代理允许您通过Java接口访问MBean,从而可以在代理上进行调用,而无需编写冗长的代码来访问远程MBean。在这里通过调用javax.management.JMX
类的newMBeanProxy()
方法创建了Hello
的MBean代理,将MBean的MBeanServerConnection
、对象名称、MBean接口的类名和true
传递给它,以表示代理必须作为一个NotificationBroadcaster
行为。JMX客户端现在可以执行由Hello
定义的操作,就像它们是本地注册的MBean的操作一样。JMX客户端还添加了一个通知侦听器,并更改了MBean的CacheSize
属性,以使其发送通知。
您可以使用与创建MBean代理相同的方式创建MXBean代理。
... ObjectName mxbeanName = new ObjectName ("com.example:type=QueueSampler"); QueueSamplerMXBean mxbeanProxy = JMX.newMXBeanProxy(mbsc, mxbeanName, QueueSamplerMXBean.class); QueueSample queue1 = mxbeanProxy.getQueueSample(); echo("\nQueueSample.Date = " + queue1.getDate()); echo("QueueSample.Head = " + queue1.getHead()); echo("QueueSample.Size = " + queue1.getSize()); echo("\nInvoke clearQueue() in QueueSampler MXBean..."); mxbeanProxy.clearQueue(); QueueSample queue2 = mxbeanProxy.getQueueSample(); echo("\nQueueSample.Date = " + queue2.getDate()); echo("QueueSample.Head = " + queue2.getHead()); echo("QueueSample.Size = " + queue2.getSize()); ...
如上所示,要为MXBean创建代理,您只需调用JMX.newMXBeanProxy
而不是newMBeanProxy
。MXBean代理mxbeanProxy
允许客户端调用QueueSample
MXBean的操作,就像它们是本地注册的MXBean的操作一样。
一旦JMX客户端获取了所有所需的信息并在远程JMX代理的MBean服务器上执行了所有必需的操作,连接必须关闭。
jmxc.close();
通过调用JMXConnector.close
方法来关闭连接。
此示例要求Java SE平台的版本为6。要使用自定义JMX客户端Client
远程监视Main
JMX代理,请按照以下步骤进行:
jmx_examples.zip
保存到你的 work_dir
目录中。unzip jmx_examples.zip
work_dir
目录中编译示例 Java 类。
javac com/example/*.java
Main
应用程序,指定公开 Main
进行远程管理的属性:
java -Dcom.sun.management.jmxremote.port=9999 \ -Dcom.sun.management.jmxremote.authenticate=false \ -Dcom.sun.management.jmxremote.ssl=false \ com.example.Main
将生成等待某些事件发生的确认。
Client
应用程序:
java com.example.Client
显示已获取 MBeanServerConnection
的确认。
显示了在 Main
启动的 MBean 服务器中注册的所有 MBean 的域。
显示了在 MBean 服务器中注册的 MBean 的数量,以及所有这些 MBean 的对象名称。显示的 MBean 包括在 Java VM 中运行的所有标准平台 MXBean,以及由 Main
在 MBean 服务器中注册的 Hello
MBean 和 QueueSampler
MXBean。
通过 Client
调用了 Hello
MBean 的操作,以下是操作的结果:
Client
中以侦听来自 Main
的通知。CacheSize
属性的值从 200 更改为 150。Main
的终端窗口中,显示了 CacheSize
属性更改的确认。Client
的终端窗口中,显示了来自 Main
的通知,通知 Client
CacheSize
属性的更改。Hello
MBean 的 sayHello
操作。Main
的终端窗口中,显示了消息 "Hello world"。Hello
MBean 的 add
操作。由 Client
显示结果。通过 Client
调用了 QueueSampler
MXBean 的操作,以下是操作的结果:
QueueSample
的值 date
、head
和 size
。clearQueue
操作。Client
关闭与 MBean 服务器的连接,并显示确认。