工作方式
到此为止所阅读的基础内容是托管 bean 或 MBean 的概念。可以把 MBean 当成资源的管理接口 的可编程表示。用更简单的术语来说,可以把它们当成围绕在受控实体周围的 Java 包装器。而用更实际的术语来说,MBean 就是 Java 类,这些类的 public 方法是根据定义良好的规则集编写的;这些规则要求把受管理的应用程序或资源的那些特征进行完整的封装。最终,资源(不论是什么以及在网络的什么位置上)的管理者为了控制的目的定位并使用对应的 MBean。
通过 API,MBean 提供以下信息,如图 5 所示:
- 资源的当前状态,通过资源的属性 提供
- 管理代理能够在资源上执行的操作
- 能够发送到有兴趣的合作方的可能的事件通知
图 5. MBean 客户机利用属性、操作和事件
MBean 创建好之后,需要注册到 MBean 服务器上。除了充当 MBean 的注册表,MBean 服务器还提供了让管理系统发现和利用已注册 MBean 的方式。管理已注册 MBean 的附加功能,由 JMX 代理服务 执行。这类服务包括:监视 MBean 的属性值,把 MBean 的改变通知给有兴趣的合作方,周期性地把 MBean 的特定信息通知给侦听器,维持 MBean 之间的关系。JMX 的代理服务通常是 MBean 本身。
MBean 服务器与必需的 JMX 代理服务的结合,被称作 JMX 代理,如图 6 所示:
图 6. JMX 代理
JMX 代理可以让它的托管资源 —— 也就是说,目前注册到它的 MBean 服务器上的 MBean 集 —— 对其他远程代理可用。
在 Java 5.0 发行之前,javax.management API 是 Java 平台的可选扩展,用户可以通过独立的下载获得,并通过 Java 代码把它用作管理和监视资源的手段。在这个上下文中,资源 可以是应用程序、运行业务关键型应用程序的 J2EE 服务器、普通的旧式 Java 对象(POJO)、甚至于硬件实体(例如网络设备、机顶盒、电信设备,或者类似的东西)。资源如果可以从 Java 代码中引用,那么它就可以潜在地成为托管资源。
虽然在这里我们实际上只是涉及了 JMX 的表面,但对于认识 MXBean 来说,介绍的已经足够多了。关于 JMX 的设计和功能的全面讨论超出了本文的范围。要了解 JMX 在网络管理应用程序中负责的那部分功能的精彩概述,可以阅读 Sing Li 关于这一主题的系列(请参阅 参考资料)。
什么是 MXBean?如何使用它们?
既然知道了什么是 MBean,现在可以看看在 java.lang.management 包中定义的与它们名称类似的 MXBean。好消息是:MXBean 并没有偏离我们在讨论 MBean 时介绍的概念。这个包中的大多数类型都是符合命名规范的接口,命名规范与标准 MBean 使用的规范类似:平台资源的名称加上后缀 MXBean。(对于标准的 MBean,当然使用后缀 MBean。)
表 1 描述了通过 java.lang.management 包中提供的 MXBean 接口可以使用的平台资源:
表 1. 可以通过 MBean 管理的平台资源
| 平台资源 | 对应的 MXBean | 可使用的数量 |
|---|---|---|
| 编译 | CompilationMXBean | 0 或 1 |
| 垃圾收集系统 | GarbageCollectorMXBean | 至少 1 |
| 内存 | MemoryMXBean | 恰好是 1 |
| 内存管理器 | MemoryManagerMXBean | 至少 1 |
| 线程 | ThreadMXBean | 恰好是 1 |
| 操作系统 | OperatingSystemMXBean | 恰好是 1 |
| 运行时系统 | RuntimeMXBean | 恰好是 1 |
| 类装入系统 | ClassLoadingMXBean | 恰好是 1 |
| 内存资源 | MemoryPoolMXBean | 至少 1 |
对于每个 MXBean,客户必须编程的接口都在 Java 5.0 规范中做了严格的设置。目前客户还无法定制这样的接口,即它公开平台的任何更加可管理的属性。
在表 1 的第三列中指出的每个 MXBean 类型可能有的实例数量,严重依赖于被管理的具体的平台系统。例如,虽然 JVM 规范允许实现者选择所使用的垃圾收集算法,但是完全有理由使用任意数量的垃圾收集器,所以在任意时间内,就会有任意数量的 GarbageCollectionMXBean 实例在活动。请把这个与 OperatingSystemMXBean 对比,后者只有一个实例可用,因为管理的虚拟机显然在指定时间内只能运行在一个操作系统上。
客户机代码可以安全地把一次性的 MXBean 当成虚拟机中真正的单体。任何时间,只要引用请求的是这些一次性类型,得到的回答总是同一个实例,而不论引用请求从何而来或者在虚拟机生命周期中什么时候发生。即使多个客户机都在监视一个虚拟机的时候,也符合这种情况。
接口 javax.management.MBeanServerConnection 是 javax.management.MBeanServer 接口的超类型,如果 MBean 服务器与客户机代码运行在同一个 JVM 中(即管理客户机和 JMX 代理共同位于同一个虚拟机中),就可以用这个接口调用 MBean 服务器。因为在 MBeanServerConnection 和 MBeanServer 之间有父子关系,所以客户可以用相同的方法调用与远程或本地 MBean 服务器交互。
对 Java 客户机代码来说,MXBean 实例的行为就像任何 POJO 一样。可以直接调用对象来取得信息,不需要其他参与者。当然,这种情况需要 Java 客户机已经直接得到了对本地 bean (与管理应用程序运行在同一个虚拟机上)的引用,或者对于封装远程虚拟机的 bean 已经请求了对它的代理。在两种情况下,引用都是从平台的单体 ManagementFactory 获得的。
也可以通过 javax.management.MBeanServerConnection 访问平台 bean,但是在这种情况下,在会话中多出了额外的一级间接。在 通过平台服务器监视远程虚拟机 一节中将看到,在这种场景中,客户机总是请求 MBeanServerConnection 代表自己来定位指定的远程 bean,并进行调用。这实际还是让 JMX(前面提到过)发出对远程 MBean 的调用,而远程客户机必须与注册 MBean 的 MBean 服务器通信。
MXBean 不是 JavaBean
为了避免混淆,应当记住:虽然把 MXBean 当成有助于监视和控制 JVM 的 MBean 完全没错,但如果把 MXBean 当成一种 JavaBean,就肯定不对 了。JavaBean 技术是 Java 平台的组件模型,它的设计目的是提供用图形化工具从可重用 Java 组件构造应用程序的能力。虽然 JavaBean 的一些特性(例如用有意义的命名规范帮助工具发现属性)在 MBean 和 MXBean 领域中都存在,但是两种技术是完全不同的,不要把它们混淆了。
额外的 MXBean
在本文开始时,我们提到过 java.lang.management 包容纳了平台管理 API。现在,我们对这句话稍做修正,因为不是所有的 MXBean 都包含在这个包中。因为 LoggingMXBean 与 Java 平台 的日志功能捆绑得如此紧密,所以把它放在 java.util.logging 包中更有意义。顾名思义,这类 MXBean 提供了运行虚拟机的日志功具的管理接口。使用对这个 bean 的引用,客户可以获得在平台上注册的所有日志程序的名称和它们彼此之间的关系。还可以获得和设置指定平台日志程序的级别。
就像 OperatingSystemMXBean 和 ThreadMXBean(另两个示例)一样,LoggingMXBean 在运行的虚拟机中也以单体方式存在。对它的已公开属性的任何 get 和 set,不论通过任何通信方式,最后都路由到同一个对象实例。
