【翻译JMX1.4】II-JMX-Agent-Specification(持续更新)

第二部分。 JMX代理规范

5.代理架构(Agent Architecture)

本章概述了Java管理扩展(JMX)代理架构及其基本概念。 它作为JMX代理的介绍规范。

5.1概述(Overview)

JMX代理是在Java虚拟机(JVM)中运行的管理实体充当MBeans和管理应用程序之间的联络人。 一个JMX代理由一个MBean服务器组成,一组代表被管理的MBean资源,作为MBean实现的最少数量的代理服务,并且通常至少有一个协议适配器或连接器。

JMX代理体系结构中的关键组件可以进一步定义如下:

  • 代表管理资源的MBean,如第I部分“JMX”中所述 仪表规范“
  • MBean服务器,这个架构和中央注册中心的关键的MBean。所有应用于MBean的管理操作都需要通过 MBean服务器。
  • 代理服务可以是本规范中定义的组件或由第三方开发的服务。由JMX定义的代理服务MBean 规范提供:
    • 允许代理使用Java实例化MBean的动态加载服务类和从网络动态下载的本地库
    • 监视MBean中的属性值的功能;该服务通知其 听众在检测到某些条件后
    • 定时器服务,可以按预定时间间隔发送通知并充当 一个调度程序
    • 定义MBeans之间的关联并维护该关系的关系服务 关系的一致性

远程管理应用程序可以通过不同的协议访问代理适配器和连接器。 这些对象是代理应用程序的一部分,但它们是不属于JMX代理规范的一部分。
图5-1显示了业务代表的组件如何相互关联和相互关联管理应用。
……
FIGURE 5-1 Key Concepts of the JMX Agent Architecture

JMX体系结构允许对象在JMX上执行以下操作剂。 这些对象可以位于代理端应用程序中,也可以位于远程端管理应用。 他们能:

  • 通过以下方式管理现有的MBean:
    • 获取其属性值
    • 更改其属性值
    • 调用它们的操作
  • 获取任何MBean发出的通知
  • 通过以下方式实例化和注册新的MBean:
    • 已经加载到代理JVM中的Java类
    • 从本地机器或从网络下载的新类
    • 使用代理服务实施涉及现有的管理策略的MBean

在JMX体系结构中,所有这些操作都是直接执行或执行的间接地通过JMX代理的MBean服务器。

5.2 JMX标准代理(JMX Compliant Agent)

代理规范中描述的所有代理组件和类都是强制性的。 为了符合代理规范,JMX代理实现必须遵守提供以下组件:

  • MBean服务器实现
  • 所有代理服务:
    • 动态类加载
    • 监测 Monitoring
    • 计时器 Timer
    • 关系 Relation
      所有这些组件都在本文档和相关的API中指定由Javadoc工具生成的文档。 代理兼容性测试套件将检查所有组件是否由实现的实际提供规范。

5.3协议适配器和连接器(Protocol Adaptors and Connectors)

协议适配器和连接器使代理可以从远程管理访问应用。 它们通过MBean的特定协议提供视图在MBean服务器中实例化并注册。 他们启用管理JVM之外的应用程序可以:

  • 获取或设置现有MBean的属性
  • 对现有MBean执行操作
  • 实例化并注册新的MBean
  • 注册并接收MBeans发出的通知

Connectors用于将代理连接到启用远程JMX的管理应用程序,即使用分布式开发的管理应用程序JMX规范的服务。 这种通信涉及一个连接器代理中的服务器和管理器中的连接器客户端。

这些组件透明地传达管理操作的点对点一个特定的协议。 管理端的分布式服务提供了一个远程服务
接口到管理应用程序可以通过其执行操作的MBean服务器。 连接器是特定于给定协议的,但管理是特定的应用程序可以无差别地使用任何连接器,因为它们具有相同的远程设备接口。

Protocol adaptors通过给定的方式提供JMX代理的管理视图协议。 他们将MBean和MBean服务器的操作调整为在给定的协议中的表示,并且可能成为不同的信息型号,例如SNMP。

连接到协议适配器的管理应用程序通常特定于给定的协议。 传统管理解决方案通常就是这种情况依赖于特定的管理协议。 他们不通过访问JMX代理远程表示MBean服务器,但是通过映射的操作到那些MBean服务器。

连接器服务器和协议适配器都使用MBean服务器的服务将他们收到的管理操作应用于MBeans,并转发通知给管理应用程序。

要使代理可管理,它必须至少包含一个协议适配器或连接服务器。 但是,代理人可以包含任何数量的代理人,允许代理人执行此操作通过不同的协议同时进行远程管理。

JMX实现提供的适配器和连接器规范应该作为MBean来实现。 这允许他们按照管理以及根据需要动态加载和卸载。

6.基础类(Foundation Classes)

基础类描述用作参数类型或返回的对象各种Java管理扩展(JMX)API的方法中的值。该本章介绍的基础类有:

  • ObjectName
  • ObjectInstance
  • Attribute and AttributeList
  • JMX exceptions
    以下课程也被视为基础类; 他们被描述在第60页的“MBean元数据类”
  • MBeanInfo
  • MBeanFeatureInfo
  • MBeanAttributeInfo
  • MBeanOperationInfo
  • MBeanConstructorInfo
  • MBeanParameterInfo
  • MBeanNotificationInfo

所有基础类都包含在JMX Instrumentation API中,以便使用MBeans可以完全根据仪器规范进行开发,但可以进行操作由JMX代理。

6.1 ObjectName类

对象名称唯一标识MBean服务器中的MBean。 管理应用程序使用此对象名称来标识要在其上执行的MBean管理运作。 类ObjectName表示一个对象名称由两部分组成:

  • A domain name
  • An unordered set of one or more key properties

对象名称的组件如下所述。

6.1.1域名(Domain Name)

域名是区分大小写的字符串。 它提供了命名的结构JMX代理或全局管理解决方案中的空间。 域
名称部分可以在对象名称中省略,因为MBean服务器可以提供一个默认域。 当需要完全匹配时(请参阅“模式匹配”)第117页),省略域名将具有与使用默认值相同的结果由MBean服务器定义的域。

域名的结构如何取决于应用程序。 域名字符串可以包含除终止域的冒号(:)以外的任何字符名称和星号(*)和问号(?),它们是通配符。JMX总是处理域名作为一个整体,因此任何语义子定义在字符串内对于JMX实现是不透明的。

为了避免不同供应商提供的MBeans之间的冲突,一个有用的约定是以域名的反向DNS名称开始
指定MBeans的组织,后跟句点和字符串的解释由该组织决定。 例如,指定的MBeanSun Microsystems Inc.,DNS名称sun.com将拥有诸如com.sun.MyDomain。 这与Java语言的惯例基本相同包名称。

建议域不应该包含字符串“//”,它是保留供将来使用。

6.1.2关键属性列表(Key Property List)

关键属性列表允许您为给定的MBean分配唯一的名称域。 关键属性是属性值对,属性不需要以对应于MBean的实际属性。

关键属性列表必须包含至少一个关键属性。 它可以包含任何关键属性的数量,其顺序不重要。

键属性中的值是一个任意字符串,但不能包含任何字符串这些人物:
:”=*?
如果需要具有这些特殊字符的字符串,则存在引用机制。 使用ObjectName.quote将任何字符串转换为可用作键的引用形式属性值和ObjectName.unquote转换回原始字符串。

一个有用的约定是在每个对象名称中包含一个type属性。 就这样所有类型为user的MBean都可以匹配模式“:type = user,”。

6.1.3名称的字符串表示(String Representation of Names)

对象名称通常使用它们的字符串表示来构建和显示具有以下语法:
[domainName]:property=value[,property=value]*
可以省略域名来指定默认域。
对象的规范名称是对象的特定字符串表示名称,其中关键属性按照词汇顺序排序。 这种表示对象名称用于执行选择MBean的词典对比基于它们的对象名称。

6.1.4模式匹配(Pattern Matching)

大多数基本的MBean操作(例如create,get和set属性)需要通过其对象名称唯一标识一个MBean。 在那种情况下,完全匹配的名字被执行。

另一方面,对于查询操作,可以通过选择一系列MBean提供一个对象名称表达式。 MBean服务器将使用模式匹配对象的名称。 名称组件的匹配功能是在以下各节中进行介绍。

Domain Name
匹配语法与标准文件通配符一致,即:

  • 星号(*)与任何字符序列匹配,包括空字符
  • 问号(?)匹配任何一个单个字符

Key Property List
通配符匹配也可以使用键来对关键属性的值执行相同的匹配语法(*和?字符)。 此外,关键属性的列表可能不完整并用作模式。

也是整个关键属性的通配符; 它取代了任何数量的可以采取任何价值的关键属性。 如果整个关键属性列表被给出为,这将匹配选定域中的所有对象。 如果至少有一个键属性在列表模式中给出,通配符可以位于给定模式中的任何位置,前提是它仍然是以逗号分隔的列表:“:property = value,”和“:,property = value”都是有效的模式。 在这种情况下,对象具有给定关键属性作为其关键属性列表的子集将被选中。

如果不使用通配符,则只使用与完整关键属性列表匹配的对象名称将被选中。 同样,该列表是无序的,所以列表模式中的关键属性可以以任何顺序给出。

6.1.4.1模式匹配示例(Pattern Matching Examples)

如果在MBean服务器中注册了具有以下名称的示例MBean:

MyDomain:description=Printer,type=laser
MyDomain:description=Disk,capacity=2
DefaultDomain:description=Disk,capacity=1
DefaultDomain:description=Printer,type=ink
DefaultDomain:description=Printer,type=laser,date=1993
Socrates:description=Printer,type=laser,date=1993

以下是可以使用模式匹配执行的查询的一些示例:

  • ”将匹配MBean服务器的所有对象。 一个空字符串对象或 用作模式的空字符串(“”)名称等同于“”。
  • “:*”将匹配默认域的所有对象
  • “MyDomain:*”将匹配MyDomain中的所有对象
  • “??Domain:*”也将匹配MyDomain中的所有对象
  • “* Dom*:*”将匹配MyDomain和DefaultDomain中的所有对象
  • :description=Printer,type=laser,”将匹配以下对象:
    MyDomain:description=Printer,type=laser
    DefaultDomain:description=Printer,type=laser,date=1993
    Socrates:description=Printer,type=laser,date=1993
  • Domain:description=Printer,”将匹配以下对象:
    MyDomain:description=Printer,type=laser
    DefaultDomain:description=Printer,type=ink
    DefaultDomain:description=Printer,type=laser,date=1993
  • Domain:description=P ”将匹配与前面相同的对象, 因为P 匹配打印机而不是磁盘。

6.2 ObjectInstance类(ObjectInstance Class)

ObjectInstance类用于表示MBean对象之间的链接名称和它的Java类。 它是MBean中MBean的完整描述服务器,但它不允许您通过引用访问MBean。
ObjectInstance类包含以下元素:

  • 相应MBean的Java类名称
  • 为相应的MBean注册的ObjectName
  • 与另一个ObjectInstance相等的测试

在创建并使用MBean时返回ObjectInstance随后进行查询。

6.3属性和属性列表类(Attribute and AttributeList Classes)

这些类用于表示MBean属性及其值。 他们包含属性名称字符串及其值作为Object实例强制转换。
JMX定义了以下类:

  • Attribute类表示单个属性 - 值对
  • AttributeList类表示属性值对的列表

Attribute和AttributeList对象通常用于传达MBean的属性值,作为getter操作的结果,或作为参数的设置操作。

6.4 JMX异常

JMX异常是由不同的方法引发的一组异常JMX接口。 本节描述哪些错误情况被这些封装例外。
主要发生JMX异常:

  • MBean服务器或JMX代理程序服务在MBean上执行操作
  • 当MBean代码引发用户定义的异常时

定义的JMX异常的组织基于错误的性质大小写(运行时间与否)以及生产地点(经理,代理人或者客户)在沟通过程中)。
只有代理提出的例外才属于本版本的范围规范。 本节仅介绍由MBean引发的异常服务器。 代理服务还定义并抛出特定的异常,这些都是描述在由Javadoc工具生成的各自的API文档中。

6.4.1 JMException类和子类

6.4.2 JMRuntimeException类和子类

6.4.3 JMX异常的描述

6.4.3.1 JMException类
6.4.3.2 ReflectionException类
6.4.3.3 MBeanException类
6.4.3.4 OperationsException类
6.4.3.5 InstanceAlreadyExistsException类
6.4.3.6 InstanceNotFoundException类
6.4.3.7 InvalidAttributeValueException类
6.4.3.8 AttributeNotFoundException类
6.4.3.9 IntrospectionException类
6.4.3.10 MalformedObjectNameException类
6.4.3.11 NotCompliantMBeanException类
6.4.3.12 ServiceNotFoundException类
6.4.3.13 MBeanRegistrationException类
6.4.3.14 JMRuntimeException类
6.4.3.15 RuntimeOperationsException类
6.4.3.16 RuntimeMBeanException类
6.4.3.17 RuntimeErrorException类

7. MBean服务器(MBean Server)

本章介绍作为核心的Managed Bean服务器或MBean服务器Java管理扩展(JMX)代理基础结构的组件。

7.1 MBean服务器的角色(Role of the MBean Server)

MBean服务器是代理中MBean的注册表。 MBean服务器是组件,它提供用于操作MBean的服务。 所有管理在MBean上执行的操作通过MBeanServer接口完成。

通常,在MBean服务器中注册以下几种MBean:

  • 为管理目的代表管理资源的MBean。 这些 资源可以是任何种类的:应用程序,系统或网络资源提供Java接口或Java包装器。
  • 为代理添加管理功能的MBean。 这个功能可以 完全通用的,例如,提供日志或监控功能,或者它 可以是特定于技术或应用领域的。 其中一些MBean由JMX规范定义,其他将由。提供 管理应用开发者。
  • 基础结构的某些组件,例如连接器服务器和 协议适配器,可以实现为MBean。这允许这样的组件 从动态管理基础设施中受益。

7.1.1 MBean服务器工厂(MBean Server Factory)

JMX代理具有一个工厂类,用于通过。查找或创建MBean服务器工厂的静态方法。 这允许更灵活的代理应用程序和可能代理中的多个MBean服务器。

MBeanServer接口定义JMX代理上可用的操作。 一个JMX代理规范的实现提供了一个实现该类的类MBeanServer接口。 在整篇文档中,我们使用术语MBean服务器来参考一个可用的MBeanServer接口的实现剂。

MBeanServerFactory是一个静态方法返回实例的类实现类。 此对象作为MBeanServer的实例返回接口,从而将其他对象与MBean的任何依赖隔离服务器的实际实现类。 在创建MBean服务器时,调用者可以还要指定它所代表的JMX代理中使用的默认域的名称。

代理应用程序使用这些方法创建单个或多个MBean包含其MBean的服务器。 JMX代理规范仅定义行为的单个MBean服务器。 JMX代理中需要额外的行为包含多个MBean服务器不在本规范的范围内。

工厂还定义了用于查找已有的MBean服务器的静态方法被创建。 通过这种方式,加载到JVM中的对象可以访问现有的MBean服务器,而无需事先了解代理应用程序。

从Java 2平台标准版(J2SE 5.0平台)的5.0版开始,每个Java应用程序都有一个可以使用的平台MBean服务器java.lang.management.ManagementFactory.getPlatformMBeanServer()。此MBean Server包含特定数量的由指定的MBeanjava.lang.management包也可以作为一种方便的方式来使用在应用程序的不同模块之间共享应用程序MBean。

7.1.2 MBean服务器权限检查(MBean Server Permission Checking)

访问MBeanServerFactory类的静态方法由MBeanServerPermission类。 MBeanServerPermission扩展了基本的Java权限,并授予对以下MBean服务器操作的访问权限:

  • createMBeanServer
  • findMBeanServer
  • newMBeanServer
  • releaseMBeanServer

权限检查将在第12章“安全性”中进一步介绍。

7.1.3 MBean的注册(Registration of MBeans)

MBean服务器的首要职责是成为MBean的注册中心。MBean可以由代理应用程序或其他MBean注册。 界面的MBeanServer类允许两种不同类型的注册:

  • 实例化新MBean并在单个操作中注册此MBean。 在这种情况下,可以通过使用来加载MBean的Java类 一个默认的类加载器,或者通过明确指定要使用的类加载器。
  • 注册一个已经存在的MBean实例。

object name在注册时被分配给MBean。 对象名称是字符串,其结构在第115页的“ObjectName类”中详细定义对象名称允许在MBean的上下文中唯一地标识MBean服务器。 这种唯一性在注册时由MBean服务器检查,将拒绝具有重复名称的MBean。

7.1.3.1 MBean注册控制(MBean Registration Control)

MBean开发人员可以对注册和注销进行一些控制MBean服务器中的MBean。 这可以通过实现MBean来完成MBeanRegistration接口。 在注册和注销注册之前和之后MBean,MBean服务器动态检查MBean是否实现了MBeanRegistration接口。 如果是这种情况,则适当的回调是调用。

MBeanRegistration接口实际上是JMX的一个API元素仪器规范。 这里描述的是因为它是执行MBean服务器定义了注册控制机制的行为。

实现这个接口也是MBeans可以获得的唯一方法引用它们所注册的MBeanServer。 这意味着他们有关于他们的管理环境的信息并变得有能力对其他MBean执行管理操作。

如果MBean开发人员选择实施MBeanRegistration接口,必须提供以下方法:

  • preRegister - 这是MBean服务器之前调用的回调方法 注册MBean。 如果发生任何异常,MBean不会被注册 这种方法。该方法可能会抛出MBeanRegistrationException 将被MBean服务器再次抛出。 任何其他异常都会 被MBean服务器捕获,封装在一个 MBeanRegistrationException并再次抛出。 该方法可用于:
    • 允许MBean在其MBean服务器上保留一个引用。
    • 在MBean暴露之前执行需要完成的任何初始化到管理运作。
    • 对对象名称执行语义检查,并在可能时提供名称该对象创建时没有名称。
    • 获取有关环境的信息,例如,检查是否存在MBean所依赖的服务。 当这些所需的服务不是可用的,MBean可能会尝试实例化它们,或者提出一个ServiceNotFoundException异常。
  • postRegister - 这是MBean服务器将调用的回调方法注册MBean后。 如果MBean是,它的布尔参数将为true注册成功,如果MBean无法注册,则为false。 如果注册失败,这种方法可以释放预注册中分配的资源。
  • preDeregister - 这是MBean服务器之前调用的回调方法注销一个MBean。此方法可能会引发抛出的MBeanRegistrationException再次由MBean服务器保持不变。 任何其他异常都会被捕获MBean服务器,封装在MBeanRegistrationException中并抛出再次。 如果此方法引发任何异常,则MBean不会被注销。
  • postDeregister - 这是MBean服务器调用的回调方法注销MBean后。

图7-1描述了MBeanRegistration的方法被调用的方式MBean服务器在执行MBean注册或注销时执行。该以粗框显示的方法是MBeanServer方法,其他方法是在MBean中实现。
……

7.1.4 MBean上的操作(Operations on MBeans)

MBeanServer接口的方法定义了以下管理要在已注册的MBean上执行的操作:

  • 通过object name检索特定的MBean。
  • 通过对名称进行模式匹配来检索MBean的集合, 并且可选地借助于应用于它们的属性值的过滤器。这样的过滤器 可以通过使用“查询”中定义的查询表达式来构造 第135页。
  • 获取MBean的一个或多个属性值。
  • 调用MBean上的操作。
  • 发现MBean的管理界面,即其属性和 操作。 这就是所谓的MBean的内省。
  • 注册MBean发出的通知的兴趣。

MBean服务器的方法是通用的:它们都采用一个对象名称确定执行操作的MBean。 MBean的作用服务器将解析此对象名称引用,确定请求的操作是否被允许在指定的对象上,如果是,则调用MBea方法执行操作。 如果出现结果,则MBean服务器将其值返回给呼叫者。

在MBean服务器中调用方法需要适当的权限。权限在第12章“安全”中描述。
API中给出了所有MBean服务器操作的详细描述由Javadoc工具生成的文档。

7.1.5 MBean代理(MBean Proxies)

作为调用MBeanServer接口的通用方法的替代方法直接访问特定MBean的代码可以为其构建代理。 代理是一个实现与MBean本身相同接口的Java对象。 一种方法代理上的此接口通过MBean服务器路由到MBean。

在可能的地方使用代理而不是调用代码更简单,更不易出错MBean服务器的方法直接。

代理使用newMBeanProxy和newMXBeanProxy方法构造在类javax.management.JMX中。 该类的Javadoc详细解释如何构建和使用它们。

7.2 MBean服务器委托MBean(MBean Server Delegate MBean)

MBean服务器定义了一个名为“JMImplementation”的域,其中包含一个域MBeanServerDelegate类的MBean已注册。 这个对象标识和描述了注册的MBean服务器。 它也是广播公司由MBean服务器发出的通知。 换句话说,这个MBean就像一个代表它所代表的MBean服务器。

此代理对象的完整对象名称由JMX指定规范,如下所示:“JMImplementation:type = MBeanServerDelegate”。

委托对象提供有关MBean服务器的所有信息其中显示为字符串类型的只读属性:

  • MBeanServerId标识代理。 这个字符串的格式不是 指定,但它旨在为MBean服务器提供唯一标识符, 例如,基于主机名和时间戳。
  • 规格名称表示规格的完整名称 MBean服务器实现是基于的。 这个属性的值必须是 “Java管理扩展”。
  • SpecificationVersion指明了JMX规范的版本 这是MBean服务器实现的基础。 对于这个版本,价值该属性必须是“1.4”。 SpecificationVendor指示JMX供应商的名称 MBean服务器实现所基于的规范。 的价值这个属性必须是“Sun Microsystems”。
  • ImplementationName给出了MBean服务器的实现名称。该字符串的格式和内容由实现者给出。
  • ImplementationVersion提供了MBean的实现版本 服务器。该字符串的格式和内容由实现者给出。
  • ImplementationVendor提供MBean服务器的供应商名称 实现。该字符串的内容由实现者给出。

MBeanServerDelegate类实现NotificationBroadcaster接口并发送由此发出的MBeanServerNotificationsMBean服务器。 对于接收这些通知的对象,他们必须注册委派对象(请参阅第134页的“MBean服务器通知”)。

注 - “JMImplementation”域名保留供JMX Agent使用实现。 MBeanServerDelegate MBean不能从中注销MBean服务器。

7.3 MBean上的远程操作(Remote Operations on MBeans)

使用代理中适当的连接器服务器进行远程管理应用程序能够通过相应的操作在MBean上执行操作连接器客户端,一旦建立连接。

通常,远程客户端能够执行该操作中的一部分操作MBeanServer接口,通过该接口的父级MBeanServerConnection。因为远程连接可能会失败,所以MBeanServerConnection中的每个方法都会失败在throws子句中声明IOException。 请参阅“MBeanServerConnection接口”一节第140页。

图7-2显示了如何从远程传播管理操作管理应用程序添加到代理端的MBean。 这个例子说明了用于获取标准MBean的“State”属性的方法的传播以下情况:

  • 管理应用程序调用一个通用的getValue方法 连接器客户端,它充当MBean服务器的远程表示。 这个动态调用类型通常与MBean结合使用 内省功能可动态发现管理界面 的MBean,甚至是远程应用序。
  • 管理应用程序直接在代理上调用getState方法通常从MBean类自动生成的对象(在这种情况下的Java应用程序)。 代理对象依赖于连接器的接口客户端将请求传送给代理并最终传送到MBean。该响应遵循反向返回路径。

….

7.4 MBean服务器通知(MBean Server Notifications)

MBean服务器将在MBean注册时始终发出通知注销。 为此定义了Notification类的特定子类用途:MBeanServerNotification类,包含对象名称列表参与该行动。

MBean服务器对象本身不会广播通知:它的唯一代理MBean实现NotificationBroadcaster接口来广播通知在它的地方。

要注册MBean服务器通知,监听器将调用与注册时一样,MBean服务器的addNotificationListener方法MBean通知,但它将提供MBean的标准化对象名称服务器委托对象(请参阅第121页的“MBean服务器委托MBean”)。

在接收MBean通知时,对象必须实现NotificationListener接口接收MBean服务器通知。

通过它的委托,MBean服务器发出以下两种类型的通知:

  • JMX.mbean.registered - 此通知指示一个或多个MBean已被注册。 通知将传达这些对象名称的列表 的MBean。
  • JMX.mbean.unregistered - 此通知指示一个或多个MBean已被注销。 通知传达了这些列表MBeans的对象名称。

注 - 当注册的属性时,MBean服务器不发送通知MBean更改值。 实施时,处理这种类型的通知直接由MBean执行,如第58页上的“属性更改通知”中所述。

7.5查询(Queries)

查询根据它们的对象从MBean服务器中检索MBean集合名称,它们的当前属性值或两者。 JMX规范定义了用于构建查询表达式的类。 这些对象然后传递给MBeanServer接口执行查询的方法。

执行查询的MBeanServer接口的方法是:

  • queryMBeans(ObjectName名称,QueryExp查询) - 返回一个Set包含MBean的对象实例(对象名称和类名称对) 匹配名称和查询。
  • queryNames(ObjectName名称,QueryExp查询)返回一个Set 包含与名称和查询匹配的MBean的对象名称。

这两种方法的参数含义是相同的。 对象名称参数定义了一个模式:查询的范围是其对象的MBeans集合名字满足这种模式。 查询表达式是用户定义的标准基于其属性值过滤作用域内的MBean。 如果任一查询方法找不到在给定范围内或满足给定查询的MBean表达式或两者,返回的Set将不包含元素。

当对象名称模式为空时,范围等同于所有MBeanMBean服务器。 当查询表达式为空时,MBean不被过滤,结果等同于范围。 当两个参数都为空时,结果就是集合所有在MBean服务器中注册的MBean。

在MBean服务器中注册的所有MBean的集合始终包含该委托MBean,以及任何注册MBean的计数。 其他查询也可以返回委托MBean,如果其对象名称在范围内并且它满足查询表达式(如果有)(请参阅第121页的“MBean Server委托MBean”)。

7.5.1查询的范围(Scope of a Query)

范围由对象名称模式定义:请参阅第117页上的“模式匹配”。只有那些对象名称与模式匹配的MBean才会被考虑查询。 查询表达式必须应用于作用域中的每个MBean,以过滤查询的最终结果。 如果查询机制得到正确实施并且用户给出了相关的对象名称模式,查询的范围可以大大的提高减少查询的执行时间。

该模式可能是一个完整的对象名称,这意味着该对象的范围该查询是单个MBean。 在这种情况下,查询等同于测试存在具有该名称的注册MBean,或者如果查询表达式不存在null,测试该MBean的属性值。

7.5.2查询表达式(Query Expressions)

查询表达式是根据属性值的约束(例如“等于”和“小于”的数字值和“匹配”的字符串)。这些限制可以然后由关系运算符(和,或者,而不是)形成复杂关联涉及几个MBean属性的表达式。

例如,代理或经理应该能够表达一个查询,例如:“检索属性年龄至少为20的MBean和属性名字以G开头,以ling结尾“。

查询表达式一次在单个MBean上进行评估,当且仅当表达式为真,则MBean包含在查询结果中。 MBean服务器测试表达式在查询范围内针对每个MBean单独表达。不是这样查询表达式可能适用于多个MBean:没有用于定义交叉MBean约束的机制。

如果对范围中的给定MBean的查询表达式进行评估,则结果为异常,MBean从查询结果中被忽略。例外不是传播给queryMBeans或queryNames的调用者。错误(的子类)java.lang.Error)可以传播,但是。

为开发查询表达式定义了以下类和接口:

  • QueryExp接口标识完整查询表达式的对象。这些对象可以在查询中使用或组成更复杂的查询
  • ValueExp和StringValueExp接口标识代表的对象 数字和字符串值,分别用于限制属性 值.
  • AttributeValueExp接口标识表示属性的对象 参与约束。 Query类支持查询的构造。它包含静态方法返回相应的QueryExp和ValueExp对象。
  • ObjectName类(请参阅第115页的“ObjectName类”)实现QueryExp接口并可用于查询中。

实际上,用户不会实例化ValueExp和QueryExp实现直接上课。 相反,他们依靠Query类的方法来返回值和表达式,将它们组合在一起以形成最终的查询表达式。

7.5.2.1查询类的方法(Methods of the Query Class)

Query类的静态方法用于构造值,约束,和查询表达式的子表达式。

以下方法返回可用作a的一部分的ValueExp实例约束,如下所述:

  • classattr - 结果表示MBean的类名称,并且只能是 用于字符串约束。
  • attr - 结果表示指定属性的值。这个结果可以用于布尔值,数字或字符串约束,取决于类型 属性。属性也可以受到其他属性值的限制 等效类型。这个方法被重载以获取类名:这是相当于为MBean的类的名称设置一个约束。 如果作用域中的MBean没有给定名称的属性,或者如果有一个类名参数,它不匹配MBean的类,然后是 查询结果中省略了MBean。
  • value - 结果表示方法参数的值,并使用它在一个约束中。该方法被重载以采用以下任何一种类型:
    • java.lang.String
    • java.lang.Number
    • int
    • long
    • float
    • double
    • boolean
      在所有这些情况下,必须在一个约束中使用结果值 等价的属性值。
  • plus,minus,times,div -这些方法每个都需要两个ValueExp参数并返回一个表示操作结果的ValueExp对象。这些 操作仅适用于数值。这些方法对于 在同一个MBean的两个属性之间构造约束。

以下方法表示对一个或多个值的约束。他们拿ValueExp对象并返回一个QueryExp对象,该对象指示约束是否为在运行时满意。这个返回对象可以用作查询表达式,或者它可以用逻辑运算符组成一个更复杂的表达式。

  • gt,geq,lt,leq,eq -
    这些方法表示标准的关系运算符在两个数值之间,分别为:大于,大于或等于,小于,小于或等于,等于。如果关系满足约束条件对于给定顺序的参数是正确的。
    between - 此方法表示第一个参数所在的约束 严格在其他两个参数所定义的范围内。所有参数都必须 是数字值。
    in -此方法等同于a之间的多个“等于”约束 数值参数和数值的数组。约束是 如果数值等于任何一个数组元素,则满足(true)。
    match -此方法表示属性值与a之间的相等性 给定字符串值或字符串模式。该模式承认通配符(*和?),字符集([Aa])和字符范围([A-Z])具有标准含义。 该属性必须有一个字符串值,如果匹配,则该约束满足 该模式。
    initialSubString,finalSubString,anySubString - 这些方法表示属性值和给定子串之间的子串约束 值。如果子字符串是前缀,后缀或任何子字符串,则约束满足 的属性字符串值,分别。
    isInstanceOf - 此方法表示MBean是一个约束 给定类的实例,由一个字符串命名。此查询类型不存在于 在1.3版本之前的这个规范的版本,所以它不应该在什么时候使用 与实施早期版本的代理进行远程交互。

一个约束可以被看作是计算一个布尔值并且可以被用作a子表达式转换为以下方法。 约束还返回一个QueryExp对象可以在查询中使用,也可以作为更复杂的子表达式使用相同的方法进行查询:

  • and- 结果表达式是两个子表达式的逻辑与 参数。 如果第一个子表达式为假,则不计算第二个子表达式。
  • or-结果表达式是两个子表达式的逻辑或 参数。 如果第一个子表达式为真,则不评估第二个子表达式。
  • not- 结果表达式是单个子表达式的逻辑否定论据。
7.5.2.2查询表达式示例(Query Expression Examples)

使用这些方法,本节开头提到的示例查询是建设如下。 当在字符串值上构造约束时,星号(*)是a通配符可以替换任意数量的字符,包括零。或者,程序员可以使用查询的子字符串匹配方法类。

CODE EXAMPLE 7-1 Building a Query

QueryExp exp = Query.and(
    Query.geq(Query.attr("age"),
        Query.value(20)),
    Query.match(Query.attr("name"),
        Query.value("G*ling")));

大多数查询都遵循上述模式:MBean的命名属性为受程序员定义的值约束,然后组成查询几个属性。 提供的所有公开属性都可用于过滤目的它们可以受数值,布尔值或字符串值的约束。

也可以根据Java类的名称执行查询使用Query类的classattr方法实现MBean。 (这个然而,功能大部分被Query.isInstanceOf查询取代。)代码示例7-2显示了如何构建用于过滤所有MBean的查询虚构类managed.device.Printer。 这个约束也可以组成对属性值进行约束以形成更具选择性的查询表达式。

CODE EXAMPLE 7-2 Building a Query Based on the MBean Class

QueryExp exp = Query.eq(
    Query.classattr(),
    Query.value(“managed.device.Printer”));

7.5.3查询例外(Query Exceptions)

执行查询可能会导致某些特定于过滤的异常方法。 如果对给定MBean的查询的评估生成其中的一个异常时,查询结果中将省略MBean。 应用程序代码不会在通常情况下查看这些例外。 只有当应用程序本身抛出异常,或者如果它调用QueryExp.apply,它是否会看到这些异常。

7.5.3.1 BadAttributeValueExpException类
7.5.3.2 BadStringOperationException类
7.5.3.3 BadBinaryOpValueExpException类
7.5.3.4 InvalidApplicationException类

7.6 MBeanServerConnection接口

JMX 1.2规范引入了一个新的接口MBeanServerConnection,MBeanServer的父接口。 这个接口的目的是提供一个用于访问MBean服务器的通用类型,无论它是否是远程的,即通过连接器或本地访问,并直接作为一个访问Java对象。

MBeanServerConnection接口类似于MBeanServer,但有两个主要区别:

  • 它省略了仅适用于本地访问的以下方法 MBean服务器:
    • instantiate。此方法对创建参数实例很有用 MBean方法或构造函数,当它们是类未知的类时 调用者的类加载器。但远程客户端的类加载器必须知道类 能够反序列化它们。
    • registerMBean。此方法将本地对象注册为MBean MBean服务器。以这种方式注册远程对象是没有意义的。
    • getClassLoader,getClassLoaderFor,getClassLoaderRepository。 这些方法对连接器的服务器端很有用。 (请参阅“使用 更正类参数的类加载器“。)类加载器和类加载器存储库通常不可序列化,因此它们不能传输到远程客户端。无论如何,它不适合遥控器 客户端可以访问这些信息。
    • deserialize.。这个方法返回一个ObjectInputStream,这不是一个 可序列化的类,所以它不能传输到远程客户端。方法 仅用于连接器的服务器端,甚至在那里它被取代 通过getClassLoader(etc)方法。
  • 其余的每个方法都在其throws子句中包含java.io.IOException。

与MBeanServerConnection交互的应用程序代码与本地应用程序一起工作MBean服务器或连接器的客户端,无论它是否是连接到服务器或连接器。

由于MBeanServerConnection的所有方法都可以抛出IOException,调用它们的应用程序代码必须准备好处理这个异常妥善处理。 对于本地MBean服务器,这些例外情况不能发生,但代码必须处理它们。 这是要付出的代价在本地和远程情况下都以同样的方式运行。

7.7更改MBean服务器实现(Changing the MBean Server Implementation)

从JMX规范的1.2版本开始,系统属性可以设置javax.management.builder.initial来替换默认值
用不同的实现来实现MBeanServer接口。当createMBeanServer或newMBeanServer方法的时候
MBeanServerFactory类被调用,它会查询这个属性。如果存在一个值,那么它必须命名一个作为其子类的公共类javax.management.MBeanServerBuilder。该类被实例化并用于创建一个MBeanServer实例。

一个MBeanServerBuilder必须能够创建一个实例MBeanServerDelegate和MBeanServer的一个实例。该MBeanServerDelegate可以是标准例如,javax.management.MBeanServerDelegate或自定义子类,重写实现名称属性。 MBeanServer可以是一个完成MBeanServer接口的重新实现,或者它可以建立在MBeanServer上标准实现通过实例化javax.management.MBeanServerBuilder,调用它的newMBeanServer方法,并将生成的对象包装到另一个MBeanServer对象中。

8.高级动态加载(Advanced Dynamic Loading)

本章介绍基于Java的类加载器的动态加载服务功能来提供使用新的检索和实例化MBean的能力
Java类和可能的本地库。 这些类和库的起源是在部署MBean服务器时不一定是已知的,并且可以包含代码从远程服务器加载。

动态加载通常由管理小程序(m-let)服务执行用于实例化从远程URL获取的MBean(通用资源定位器)在网络上。

Java管理扩展(JMX)规范也定义了较低级别类加载机制,允许开发人员扩展功能m-let服务或在没有它的情况下加载类。

本章介绍所有兼容JMX代理的强制功能。

8.1 M-Lets概述

m-let服务允许您从一个实例化并注册一个或多个MBean远程URL,位于MBean服务器中。 m-let服务通过加载m-let来完成此操作文本文件,指定要获取的MBean的信息。 信息每个MBean都在与XML中使用的标签类似的标签中指定,称为MLET标签。M-let文本文件的位置由URL指定。 当一个m-let文本文件是加载后,下载MLET标签中指定的所有类,并为每个类指定一个实例文件中指定的MBean已创建并注册。

m-let服务本身作为一个MBean实现,并在MBean中注册服务器,所以它可以被其他MBean,代理应用程序或远程使用管理应用。

图8-1说明了m-let服务的操作。

……
FIGURE 8-1 Operation of the M-Let Service

8.2 MLET标签(The MLET Tag)

m-let文件可以包含任意数量的MLET标签,每个标签用于实例化不同的标签JMX代理中的MBean。 MLET标签具有以下语法:

<MLET
CODE = class | OBJECT = serfile
ARCHIVE = "archivelist"
[CODEBASE = codebaseURL]
[NAME = MBeanName]
[VERSION = version]
>
[arglist]
</MLET>

这个标签的元素解释如下:

  • CODE = class 该属性指定完整的Java类名称,包括包名称 MBean被获得。必须包含MBean的已编译的.class文件在由ARCHIVE属性指定的其中一个JAR文件中。代码或者 OBJECT属性必须存在。
  • OBJECT = serfile 该属性指定包含序列化表示的.ser文件 要获得的MBean。该文件必须包含在其中一个JAR文件中由ARCHIVE属性指定。如果JAR文件包含目录层次结构, 此属性必须指定该层次结构中文件的路径,否则为a 匹配不会被发现。
  • ARCHIVE = archiveList 这个强制属性指定了一个或多个包含MBean或.jar的JAR文件MBean使用的其他资源。其中一个JAR文件必须 包含由CODE或OBJECT属性指定的文件。如果存档列表包含 多个文件:
  • 每个文件必须用逗号(,)与下一个文件分开
  • 整个列表必须用双引号(“”)括起来 归档列表中的所有JAR文件必须存储在 代码库URL,或者与m-let文件相同的目录,即默认代码当没有给出基础时。
  • CODEBASE = codebaseURL 此可选属性指定要获取的MBean的代码库URL。它标识包含由ARCHIVE指定的JAR文件的目录 属性。当JAR文件与目录不在同一目录中时使用此属性m-let文本文件。如果未指定此属性,则为m-let文本的基本URL 文件被视为代码库的URL。
  • NAME = MBeanName 此可选属性指定要分配的对象名称的字符串格式当m-let服务将其注册到MBean服务器时,将其发送到MBean实例。
  • VERSION =版本 此可选属性指定MBean的版本号和关联的 JAR文件被获取。 该版本号可用于指定JAR文件是否需要从服务器加载以更新已由m-let服务加载的服务。 该版本必须是一系列由每个分隔的非负十进制整数 小数点(。),例如2.14。
  • arglist MLET标记的可选内容指定一个或多个参数列表 传递给MBean的构造函数进行实例化。 m-let服务寻找具有与指定的参数类型相匹配的签名的构造函数 在arglist中。使用非默认构造函数实例化对象 构造函数仅限于有字符串的构造函数参数 表示。arglist中的每个项目都对应于构造函数中的参数。使用 以下语法来指定argList: 哪里:
  • argumentType是参数的类(例如Integer)
  • argumentValue是参数值的字符串表示形式

8.3 M-Let服务(The M-Let Service)

m-let服务的类是javax.management.loading的成员包。 MLet类实现包含方法的MLetMBean用于远程访问。 这意味着m-let服务本身就是一个MBean和可以像这样管理。

MLet类还扩展了java.net.URLClassLoader对象,这意味着它本身就是一个类加载器。 这允许几个快捷方式来加载没有的类需要一个m-let文件。

8.3.1从URL加载MBean(Loading MBeans From a URL)

m-let服务的getMBeansFromURL方法执行类加载基于远程服务器上的m-let文本文件。 m-let文件和类文件需要可以在服务器上使用,如第144页的“MLET标签”中所述此方法的重载版本将URL参数作为字符串或java.net.URL对象。

m-let文件中的每个MLET标记描述了一个要下载和创建的MBean在MBean服务器中。 当对getMBeansFromURL方法的调用成功时,新下载的MBean在JMX代理中实例化并注册使用MBean服务器。 这些方法返回MBeans的对象实例被成功创建,并为那些不成功的对象抛出一个可抛出的对象。

MLet类的其他方法管理本地库的目录以JAR文件格式下载并由某些MBeans使用。 请参阅API文档由Javadoc工具生成更多细节。

8.3.2类加载器功能(Class Loader Functionality)

m-let服务使用其类加载器功能来访问中给出的代码库一个m-let文件或由URL本身提供。这个代码库可以在m-let中使用用于从相同的代码库下载其他MBean的服务。

例如,一个m-let文件可以指定一些MLET标签来填充所有的JMX代理中的MBean。一旦getMBeansFromURL方法被调用做到这一点,m-let服务可以用来再次实例化这些MBean中的任何一个,或者在相同的代码库中的任何其他类。

这是通过将m-let服务的对象名称作为类加载器参数传递给MBean服务器的createMBean方法(请参阅相应的API由Javadoc工具生成的文档)。因为代码库已经被m-let服务访问,其类加载器功能可以访问代码再次基地。在这种情况下,MLET标签中的信息不再被采纳帐户,尽管可以使用createMBean方法的参数指定参数给类构造函数。

因为MBeanServer接口的createMBean方法需要该对象类加载器的名称,此功能也可用于远程管理在JMX代理中没有直接对象引用的应用程序。

m-let服务MBean还公开用于指定代码的addURL方法而不需要访问任何m-let文件。这些方法添加代码库由指定的URL指定给m-let服务的类加载器。 MBean类在此代码库中可以直接下载并在MBean服务器中创建通过createMBean方法,再次使用作为类给出的m-let服务加载器对象。

注 - 使用m-let服务的类加载器从中加载创建类任意代码库或从m-let代码库重新加载类意味着代理应用程序或MBean开发人员对代码库有一些预先知识运行时的内容。

8.3.2.1本地库(Native libraries)

m-let服务充当它加载的任何MBean的类加载器。这意味着如果MBean包含本地方法,并且它们加载包含该方法的本地库这些方法的代码使用System.loadLibrary,然后是m-let类加载器findLibrary方法将被调用来查找库。此方法被覆盖来自java.lang.ClassLoader。它会试图找到一个资源(通常是一个在JAR文件中输入),其名称是库的名称,在系统相关中修改办法。如果它找到了,它会将内容复制到目录中的文件中由MLet.getLibraryDirectory()方法返回,并返回名称该文件作为findLibrary的结果。这在API中进一步描述MLet.findLibrary规范。

并非所有系统都以这种方式支持本地库。一个不会的系统抛出getLibraryDirectory和UnsupportedOperationException异常MLet类中的setLibraryDirectory方法。

即使在支持此功能的系统上,最好不要依赖它因为它带来的可移植性问题。

8.4类加载器库(The Class Loader Repository)

MBean服务器在类加载器存储库中维护一个类加载器列表。该类加载器存储库有时也被称为默认加载器存储库。

类加载器存储库在以下情况下使用:

  • 在MBeanServer的createMBean和实例化方法中 接口。 类加载器存储库用于查找和加载名为。的类 这些方法的className参数。 这些方法存在于几个重载的表单中。 一些表单有一个指定作为类加载器的MBean的ObjectName参数。 班上 装载机存储库不被这些表单使用。
  • 当m-let在其URL中找不到类时,它会尝试加载该类 类加载器存储库。 这种行为可以在m-let时禁用 创建。
  • MBeanServer接口中的方法getClassLoaderRepository为MBean服务器的客户端提供了一种访问其类加载器存储库的方法 直。

如果在同一个Java虚拟机中为几个MBean服务器创建例如调用MBeanServerFactory.createMBeanServer的程序几次,每个人都有自己的类加载器存储库,独立于其他。

8.4.1如何将加载器添加到类加载器库(How to Add Loaders to the Class Loader Repository)

在创建MBean服务器时,其类加载器存储库包含类加载器用于加载MBeanServer实现类。 此后,一堂课如果注册为MBean,则加载器将添加到存储库中。 如果MBean是随后未注册,则将其从存储库中删除。

换句话说,如果一个MBean被注册为一个后代java.lang.ClassLoader,它被添加到类加载器库中。

如果MBean是java.lang.ClassLoader的后代,但实现了接口javax.management.loading.PrivateClassLoader,那么它永远不会添加到类加载器存储库。

因为类javax.management.loading.MLet是的后代java.lang.ClassLoader,m-let在添加到类加载器库时它们在MBean服务器中注册。 JMX规范包含一个类PrivateMLet子类MLet并实现PrivateMLet。 一个除了永远不会被添加到外,PrivateMLet的行为就像MLet一样类加载器存储库。

8.4.2类加载器库中的加载器的顺序(Order of Loaders in the Class Loader Repository)

存储库中类加载器的顺序非常重要。当一个类被加载使用存储库,每个类加载器依次被要求加载类。如果一个装载机成功加载课程,搜索停止。如果加载程序抛出ClassNotFoundException,搜索继续执行列表中的下一个加载器。如果没有加载器成功加载类,尝试结果为aClassNotFoundException异常。

类加载器存储库中的第一个加载器是用于加载该类的第一个加载器MBeanServer实现类。此后,每个条目都是一个MBeanjava.lang.ClassLoader的后代。这些装载机的顺序是英寸中的顺序MBeans被注册了。

更正式地说,如果createMBean或者.MBean m1出现在MBean m2之前,那么MBean m1会出现MBean m2之前registerMBean操作注册了m1之前完成的操作注册m2开始。如果两个操作都没有在另一个操作完成之前完成MBean同时在不同的线程中注册,并且之间的顺序m1和m2是不确定的。

8.4.3 M-Let委托给类加载器库(M-Let Delegation to the Class Loader Repository)

m-let是一个类加载器,因此它遵循一个类的标准行为加载器使用loadClass方法加载类时:

  • 首先,它向其父类加载器发送一个请求以加载该类。 父类装载程序是在创建m-let时指定的。 默认情况下,它是系统类加载器。
  • 如果父类加载器无法加载类,则m-let尝试加载它 本身通过它的URL列表。 MLet类是的一个子类java.net.URLClassLoader以及通过列表加载类的行为 的URL从URLClassLoader继承。

如果这两个尝试均未找到该类,则m-let尝试加载该类通过类加载器存储库。我们说它委托给类加载器库。只有当这种尝试也失败时,m-let才会抛出aClassNotFoundException异常。

当m-let委托给类加载器存储库时,存储库中的每个加载器被依次要求加载班级。但是,如果m-let本身就在类加载器中存储库,只要到达m-let,搜索就会停止。也就是说,只有m-let委托给存储库中的加载器。

类加载器存储库可用作使公共类可用的一种方式到来自不同来源的MBean。常见的类放在存储库中,和m-let委托给存储库可以找到它们。因为只有m-let委托给存储库中它们之前的加载程序,加载程序的顺序注册是重要的。如果m-let m1定义了mlet中的类使用的类m2,那么m1必须在m2之前注册。

当创建一个m-let时,可以控制它是否委托给其他人通过存储库的装载机,以及其他装载机是否委托给它:

  • 如果m-let是使用Boolean delegateToCLR参数构造的,则为false将不会委托给类加载器存储库。
  • 如果m-let是PrivateMLet的一个实例,则它不会被添加到该类中装载机存储库,所以其他装载机不会委托给它。
8.4.3.1 JMX 1.2规范中的新语义(New Semantics in the JMX 1.2 Specification)

在1.2之前的JMX规范的版本中,m-let委托给完整列表类加载器存储库中的加载器。也就是说,如果一个m-let本身没有找到一个类,存储库中的每一个其他装载器都被咨询过。装载机被咨询不管它们是在库中的m-let之前还是之后。

这种行为对于某些Java虚拟机的一个微妙问题是开放的。注意一个类不一定是通过显式调用loadClass方法来加载的一些类加载器。更经常的是,一个类被加载,因为它被另一个类引用类,例如,因为它是该类中的字段的类型,或者是参数或类的字段类型在方法中返回值,或者它是该类的超类或超接口,或者是其中的一个该类中的方法构造它的一个实例,或者引用一个静态字段或方法。简化一下,我们可以说一个阶级的确切时刻加载无法预测。

当一个类c1第一次引用另一个类A时,A使用c1的类加载装载机。如果c1由m-let m1加载,则A也将使用m1加载。

如果m1没有通过它的父类加载器或通过它的列表找到类A.URL,它将委托给类加载器存储库。

参考图8-2,设想在另一个线程中同时出现一个类c2,由m-let m2装载,首次提到B类。 再次,B将被加载使用m2,如果m2没有找到类本身,它将委托给类加载器库。

如果m1搜索存储库中除本身之外的所有加载程序,m2会执行此操作同样,那么m1最终会发送一个请求到m2来加载A,m2将最终结束向m1发送请求以加载B.

某些没有的Java虚拟机实现会出现问题一次允许多个线程通过给定的类加载器加载类。因为线程1正在通过m1加载类A,线程2不能同时加载B级到m1级。 因为线程2正在通过m2加载B类,线程1不能同时通过m2加载A级。 每个线程都必须等待另一个线程在它可以继续之前完成,创造一个典型的死锁情况。

……

FIGURE 8-2 Deadlock scenario for m-let delegation

语义的变化避免了这种情况,因为两个m-let必须有一个在类加载器存储库中出现在另一个之后。 如果m2出现在m1之后,则m1将会出现从来没有尝试使用m2加载一个类,因为它只委托加载器出现的时间早于存储库中的时间。 所以僵局不会发生。

如果你准备好运行僵局的风险,或者你确定这样的场景由于上述情况不会发生,所以直接将MLet子类化并覆盖它loadClass方法来恢复以前的委托给所有加载器的语义在存储库中,无论是在m-let之前还是之后。 但是,您应该记住,如果通过这样一个MLet子类加载的类引用另一个没有的类存在之前,请参阅类加载程序存储库中的所有m-let抛出ClassNotFoundException。

8.5为参数使用正确的类加载器(Using the Correct Class Loader for Parameters)

类加载的一个微妙缺陷是由类加载器cl1创建的类a.b.C与类加载器cl2创建的类a.b.C不同。 在这里,“创建”指的是实际上使用其defineClass创建类的类加载器方法。 如果cl1和cl2都通过委托给另一个类加载器cl3来找到a.b.C,则它是同一班。

由cl1创建的“a.b.C”类型的值不能分配给变量或由cl2创建的“a.b.C”类型的参数。 试图这样做会导致一个异常,如ClassCastException。

对于JMX规范,这可能会造成方法参数的问题createMBean,invoke,setAttribute和MBean服务器的setAttributes。
假设您有一个具有以下接口的MBean:
CODE EXAMPLE 8-1 Simple MBean interface:

public interface AnMBean {
public void m(SomeClass x);
}

如果MBean服务器包含由该类创建的该MBean的一个实例装载机cl1。 在某个阶段,无论是在加载过程中,还是在第一次被引用时,cl1将加载类SomeClass。

现在假设您正在编写一个连接器。 在接收端(服务器端)连接器,您将获得调用MBean上的m的请求。 发件人将发送一个您必须重新创建SomeClass的实例,例如,通过反序列化它。 如果你用cl1以外的任何类加载器重新创建它,你会在得到一个异常时您尝试将其传递给方法m。

这意味着你的连接器服务器必须有一个实例化接收的方法使用正确的类加载器的对象。

为此,MBeanServer接口中有三个与类相关的方法加载:

  • getClassLoaderFor
  • getClassLoaderRepository
  • getClassLoader

以下各节将介绍这些方法。

8.5.1 getClassLoaderFor

代码示例8-1在152页适当的方法是:
public ClassLoader getClassLoaderFor(ObjectName name);

通过使用MBean的ObjectName调用此方法,您可以获取该类加载器创建了MBean的类,在我们的示例中为cl1。 然后你可以得到正确的类,SomeClass,使用cl1。

getClassLoaderFor方法适用于invoke,setAttribute,和setAttributes操作,因为适当的类加载器
这些操作的参数是目标MBean的类加载器。

getClassLoaderFor方法在JMX的1.2版本中引入规范。 以前,连接器服务器必须使用反序列化之一
MBeanServer接口中的方法。 这些方法现在已被弃用。因此,请使用getClassLoaderFor而不是反序列化(ObjectName名称,byte []数据)。

8.5.2 getClassLoader和getClassLoaderRepository

对于createMBean操作,目标MBean不存在,因为整个操作的目的是创建它。 有两类createMBean操作,具体取决于是否有指定的loaderName参数作为用于加载MBean类的类加载器的MBean的名称。

  • 对于不包含loaderName的createMBean操作,MBean 类使用类加载器存储库进行加载。 如果构造函数被调用创建MBean有参数,那么这些也应该使用类加载 加载器存储库,以避免上面针对invoke解释的问题。因此,MBeanServer接口包含一个方法:
    public ClassLoaderRepository getClassLoaderRepository();
    可以使用ClassLoaderRepository接口中的方法loadClass通过类加载器存储库加载类。
  • 对于包含loaderName的createMBean操作,MBean类为 使用以给定名称注册为MBean的类加载器加载。 如果构造函数有参数,它们的类应该由同一个类加载 装载机。因此,MBeanServer接口包含一个方法:
    public ClassLoader getClassLoader(ObjectName name);

类似的考虑适用于MBeanServer的实例化方法接口。 但是,这些方法通常不会通过连接器暴露。

方法getClassLoader和getClassLoaderRepository是在JMX规范版本1.2中引入。 以前,连接器服务器必须在MBeanServer接口中使用三种反序列化方法之一。 这些方法现在已被弃用。

因此,使用getClassLoaderRepository而不是
deserialize(String className,byte [] data)
也可以使用getClassLoader代替
deserialize(String className,ObjectName loaderName,byte [] data)

9.监测(Monitoring)

本章指定了允许您观察的监视器MBean族其他MBean中的属性值的随时间变化,并在发送通知
阈值事件。 它们统称为监测服务。

监视服务是遵从JMX的代理的强制性部分规范,并且必须全面实施。

9.1概述(Overview)

使用监视服务,可以从一个或多个给定属性中获取观察值其他MBean(观察到的MBean)会按照指定的时间间隔进行监视粒度周期。 该值是属性值或其中包含的值复杂类型的属性值。 对于每个观察到的MBean,监视器派生出一个来自这个观察的第二个值,称为派生量表。 这个派生的标准是要么是确切的观测值,要么是两者之间的差异数值类型的连续观测值。

每个监控服务发送一个特定的通知类型的派生量表满足一组条件之一。 条件被指定当监视器初始化时,或者通过监视器MBean的动态管理界面。 监视器也可以在某些错误情况下发送通知在监视属性值时遇到。

9.1.1监视器的类型(Types of Monitors)

有关MBean中属性值的信息由三个提供不同类型的显示器:

  • CounterMonitor - 使用Java整数类型(字节,整数, 短,长),表现得像一个柜台,即:
    • 它们的值总是大于或等于零。
    • 只能增加它们
    • 它们可以翻转,并且在那种情况下定义模值。
  • GaugeMonitor - 使用Java整数或浮点类型观察值(Float, Double), 表现得像一个衡量(任意增加和减少)。
  • StringMonitor - 观察String类型的值。

所有类型的监视器都扩展了抽象的Monitor类,它定义了常见的类属性和操作。 观测值的类型必须被支持使用特定的监视器子类。

但是,监视器会验证返回的对象实例的类型属性的值,而不是观察到的MBean元数据中声明的属性类型。例如,这允许字符串监视器观察声明为Object的值在其元数据中,只要实际值是String实例。

每个监视器也是一个标准的MBean,允许它们被创建和由其他MBean或管理应用程序动态配置。

9.2 MonitorNotification Class

通知类的特定子类被定义为供所有监控使用服务:MonitorNotification类。

此通知用于报告以下情况之一:

  • 检测到监视器的触发条件之一,例如高仪表的阀值达到了
  • 观察属性期间发生错误,例如观察到的错误MBean不再注册

MonitorNotification实例中的通知类型字符串标识特定的监视事件或错误情况,如图9-1所示。 a的领域MonitorNotification实例包含以下信息:

  • 观察到的MBean的对象名称
  • 观察到的属性名称或属性名称加上要观察的复杂类型属性值中的值
  • 派生量表,即从观察计算得出的最后一个值
  • 触发此通知的阈值或字符串

所有可以由生成的通知类型的树表示形式监控服务在图9-1中给出。 错误类型对所有人都是通用的监视器并在下面进行描述。 每个阈值事件都是特定于它的监视器并在相应的章节中进行介绍。

……

FIGURE 9-1 Tree Representation of Monitor Notification Types

9.2.1通用监视器通知类型(Common Monitor Notification Types)

以下通知类型对所有显示器都是通用的,并被发送到反映错误情况。 显示器启动时进行第一次测量:

  • jmx.monitor.error.mbean - 当其中一个观察到的MBean不是时发送在MBean服务器中注册。
    观察的对象名称在提供通知。
  • jmx.monitor.error.attribute - 当观察属性不发送时发送存在于其中一个观察对象中。观察对象名称和观察属性名称在通知中提供。
  • jmx.monitor.error.type -在观察对象实例时发送属性值为null或不是给定监视器的适当类型。该观察对象名称和观察属性名称在通知中提供。
  • jmx.monitor.error.runtime -所有异常(除了描述的情况上面)在尝试获取观察属性的值时发生由监视器捕获,并将在此类通知中报告。

以下通知类型对于计数器和计量监视器是通用的; 它被发射以反映特定的错误情况:

  • jmx.monitor.error.threshold - 在发生任何不一致的情况下发送监视器参数的配置:
    • Counter monitor:阈值,偏移量或模量不相同键入作为观察计数器属性。
    • Gauge monitor:低阈值或高阈值与类型不同观察到的规格属性。

9.3 CounterMonitor类

计数器监视器在观察到的计数器值达到或时发送通知超过了被称为阈值的比较水平。

计数器到达时可以翻转(也称为环绕)最大值。 在这种情况下,每次计数器触发通知达到或超过阈值,只要在阈值以下观察到自从之前的通知。 计数器不一定会翻转为零,但是这不会影响处理一般情况的显示器。

另外,偏移机制可以检测计数间隔,如下所示:

  • 只要监视器的偏移值非零,就会启用偏移机制。
  • 当显示器检测到计数器达到或超过阈值时,通知被触发并且阈值增加了偏移值。该阈值会根据需要多次增加偏移值阈值再次超过计数器值,但仍然只发送一个通知。
  • 如果监视的计数器在达到最大值时翻转,则模数值需要设置为该最大值。那么门槛将会如此当它严格超过模数值时也“翻转”。当。。。的时候阈值“翻转”时,它会重置为最近指定的值在任何偏移量之前调用监视器的setInitThreshold方法应用。
  • CounterMonitor类的getThreshold方法总是返回阈值的当前值,其中包括任何偏移增量。
  • 所有增加或翻转阈值都被认为是发生即刻,即在计数递增之前。因此,如果粒度周期适当设置,监视器每触发一次阈值通知计数时间增加一个等于偏移值的时间间隔。

如果使用计数器差异选项,那么派生的计量器的值是计算为两个连续观察计数器值之间的差值观察结果。如果计数器会翻转,那么必须定义模量计数器差异是积极的。当计数器翻转时,两者之间的差异观察结果将是负值,模数的值需要加上。在时间t计算计数器差值的派生量表值(V [t])使用以下算法,其中GP是粒度周期:

  • 当t小于StartDate + 2GP时,V [t] =(整数)0
  • 如果(counter [t] - counter [t-GP])大于或等于零,则V [t] =计数器[t] - 计数器[t-GP]
  • 如果(counter [t] - counter [t-GP])为负数,则V [t] =计数器[t] - 计数器[t-GP] +模量

计数器监视器有以下限制:

  • 阈值,偏移值和模值属性必须是与观察属性相同的整数类型。

图9-2显示了偏移量为2的计数器监视器的操作。

监视器观察到随时间t变化的计数器C(t)。 粒度周期是GP并且比较级别是T. CounterMonitor何时发送通知计数器的值达到或超过比较(阈值)级别。 后通知已经发送,阈值增加了偏移值直到比较级别大于计数器的当前值。

9.3.1计数器监视器通知类型(Counter Monitor Notification Types)

除了监视器错误通知类型外,CounterMonitor MBean还可以广播以下通知类型:

  • jmx.monitor.counter.threshold - 此通知类型在触发时触发派生量表已达到或超过阈值。

9.4 GaugeMonitor Class

仪表监视器观察表现为仪表的数值。 滞后机制是为了避免重复触发通知时仪表在阈值附近产生小振荡。 这种能力是通过成对指定阈值来提供; 一个是高门槛值另一个是低阈值。 阈值之间的差异是滞后区间。

GaugeMonitor MBean具有以下结构:

  • HighThreshold属性定义量表必须达到的值或超过以触发仅在NotifyHigh时才会广播的通知布尔属性为true。
  • LowThreshold属性定义量表必须落入或落下的值触发只在NotifyLow时才会播放的通知布尔属性设置为true。

仪表监视器有以下限制:

  • 阈值高值和阈值低值属性相同键入为观察属性。
  • 阈值高值大于或等于阈值低值。

仪表监视器具有以下行为:

  • 最初,如果NotifyHigh为true并且计量器值等于或大于此值当仪表增加时,高于阈值,然后定义通知被触发。高阈值的后续交叉点不会触发进一步的通知,直到量表值变得等于或小于低阈值。
  • 最初,如果NotifyLow为true并且量表值变得等于或小于量表减少时LowThreshold值,然后定义通知被触发。低阈值的后续交叉点不会导致进一步的通知,直到量表值变得等于或大于HighThreshold值。
  • 创建仪表时,如果NotifyHigh为真,仪表值为已经等于或大于HighThreshold值,则定义通知被触发。同样,如果NotifyLow为true并且量表值为已经等于或小于LowThreshold值,则定义通知也被触发。

如果使用标准差选项,则派生标准的值为计算为连续两次观测值的差值观察结果。

在t时刻使用计算出的量表差值的派生量表值(V [t])以下算法,其中GP是粒度周期:

  • 当t小于StartDate + 2GP时,V [t] =(整数)0
  • 否则,V [t] = gauge [t] - gauge [t-GP]

假设两者都是GaugeMonitor的操作,如图9-3所示通知开关是真的。

……
FIGURE 9-3 Operation of the GaugeMonitor

9.4.1仪表监视器通知类型(Gauge Monitor Notification Types)

除了监视器错误通知类型外,GaugeMonitor MBean还可以广播以下通知类型:

  • jmx.monitor.gauge.high - 此通知类型在触发时触发派生量表已达到或超过高阈值
  • jmx.monitor.gauge.low - 此派生的通知类型被触发仪表已降至或低于低阈值。

9.5 StringMonitor类

字符串监视器观察String类型的值。 在这种情况下派生的标准是始终是观察值。 字符串监视器被配置为一个值字符串称为字符串比较,并能够检测以下两个条件:

  • 派生量表匹配字符串与比较。 如果NotifyMatch属性的显示器为真,则发送通知。在随后的观察中时间(由粒度周期定义),则不会发送其他通知只要属性值仍然匹配字符串与比较。
  • 派生量表的值与字符串与比较值不同。如果监视器的NotifyDiffer属性为true,然后发送通知。 在随后的观察时间,只要没有其他通知将被发送属性值与字符串 -比较不同。

假设选择了两个通知,则此机制可确保匹配和不同的是严格交替的,每次都是在第一次观察条件时发生。
字符串监视器的操作如图9-4所示。 粒度周期是GP,字符串比较是“XYZ”。

……
FIGURE 9-4 Operation of the StringMonitor

9.5.1字符串监视器通知类型(String Monitor Notification Types)

除了监视器错误通知类型外,StringMonitor MBean还可以广播以下通知类型:

  • jmx.monitor.string.matches - 此通知类型在触发时触发派生量表首先匹配要比较的字符串
  • jmx.monitor.string.differs - 此通知类型在触发时触发派生量表首先不同于要比较的字符串。

9.6监视MBean的实现(Implementation of the Monitor MBeans)

图9-5提供了各种监视器MBean类的包图他们实现的接口。 由Javadoc生成的API文档工具提供了所有监视服务接口的完整描述类。
……
FIGURE 9-5 The Package and Class Diagram of the Monitor MBeans

10.定时服务(Timer Service)

计时器服务会在特定日期和时间触发通知。 它也可以触发通知以固定的时间间隔重复。 通知被发送到所有对象注册接收定时器发出的通知。 定时器服务是一个可以管理的MBean,允许应用程序设置可配置的调度。

从概念上讲,Timer类管理发送的日期通知列表当他们的日期和时间到达。 提供这个类的方法来添加和从列表中删除通知。 实际上,通知类型是由。提供的用户,以及日期和可选的周期以及重复次数。该定时器服务总是发送其特定的通知实例TimerNotification类。

10.1计时器通知(Timer Notifications)

计时器服务可以通过两种不同的方式管理通知:

  • 仅触发一次的通知
  • 以定义的周期和/或数量重复的通知事件

此行为由通知时传递给定时器的参数定义被添加到通知列表中。 每个通知添加到计时器服务被分配一个唯一的标识号码。 只有一个标识号码分配给通知,无论触发多少次。

10.1.1 TimerNotification类

定义了通知类的特定子类以供定时器使用服务:TimerNotification类。 通知类型包含在实例中
的TimerNotification类是特别的:它是由用户定义的通知被添加到定时器。 所有由定时服务广播的通知都是TimerNotification类的实例。

TimerNotification类具有唯一的通知标识符字段标识触发此通知实例的计时器通知。

10.1.2向定时器添加通知(Adding Notifications to the Timer)

定时服务维护一个已经过期的通知的内部列表请求发送。 通知被添加到这个列表使用Timer类’addNotification方法。 这些方法使用以下参数定时器创建一个TimerNotification对象,然后将其添加到列表中:

  • type - 通知类型字符串。
  • message - 通知的详细消息字符串。
  • userData - 通知的用户数据对象。
  • date - 发生通知的日期。 Timer类包括用于表示以毫秒为单位的持续时间的整型常量,然后可以使用它们创建java.util.Date对象。

除了通知之外,addNotification方法也被重载参数和日期,它可以采用以下可选参数:

  • period - 通知发生之间的时间间隔(以毫秒为单位)。如果此参数为零或为空,则不会启用重复通知。
  • nbOccurences [原文] - 通知发生的总次数。 如果此参数的值为零或未定义(空),并且如果句点为不为零或为空,那么通知将无限期地重复。

如果要插入的通知的日期在当前日期之前,那么addNotification方法的行为就像当前日期已被指定一样。更新正在添加的计时器通知的日期不会生成任何日期通知事件,而不是sendPastNotifications机制定时器启动时应用(请参阅“启动和停止定时器”打开第168页)。

addNotification方法返回新的计时器通知的标识符。该标识符可用于从中检索关于通知的信息定时器或从定时器的通知列表中删除通知。 然而,通知已添加到通知列表后,与其关联参数不能更新。

当发生一次性通知(周期为零或空)时,它将从中删除定时器的通知列表。

10.1.3接收计时器通知(Receiving Timer Notifications)

定时器服务MBean是一个带通知的标准通知广播器类型和时间由通过建立的通知列表定义addNotification方法。给定定时器MBean的所有侦听器都将收到其所有的侦听器计时器通知。配置为监听特定计时器通知的监听器在注册为侦听器时应指定适当的过滤器对象(请参阅“NotificationFilter接口”在第58页)。

当定时器处于活动状态并且定时器通知的日期到期时,定时器服务以给定类型,消息和用户数据广播该通知,以及定时器内的通知标识符。如果有定期通知指定的出现次数,该数字减1。访问定时器通知的出现参数总是返回剩余的访问时发生的次数。

当通知没有重复或已经用完时它会从定时器的通知列表中删除。的方法如果调用,则用于访问通知参数的Timer类将引发异常带有发送和删除的定时器通知的标识符。

10.1.4从定时器167中删除通知(Removing Notifications From the Timer)

计时器通知也可以使用其中一个从通知列表中删除遵循Timer类的方法:

  • removeNotification - 将通知标识符作为参数和从列表中删除相应的通知.
    如果指定了标识符不存在于列表中,此方法抛出InstanceNotFoundException。
  • removeNotifications - 将通知类型作为参数并删除列表中添加了该类型的所有通知。
    如果指定通知类型不对应于列表中的任何通知,此方法抛出一个InstanceNotFoundException异常。
  • removeAllNotifications - 清空计时器的通知列表。 这个方法还会重置通知标识符,这意味着所有现有的标识符对于这个计时器是无效的,并会错误地引用新的通知。

10.2启动和停止定时器(Starting and Stopping the Timer)

定时器服务(由Timer类的一个实例表示)使用激活启动方法并使用停止方法停用。如果通知列表计时器启动时为空,计时器等待添加通知。没有定时器通知在定时器启动之前或停止之后触发。

您可以通过调用定时器来确定定时器是否正在运行方法isActive。如果计时器正在运行,isActive方法返回true。

如果计时器列表中的任何通知都有关联的日期已过当定时器启动时,定时器尝试更新它们。定期的日期通知按其间隔时间递增,直到日期大于当前日期。增量的数量可以受限于其定义的数量的事件。在开始日期和时间之前的一次性日期的通知通知数量有限,无法更新为超过开始日期将从计时器的通知列表中删除。

在定时器启动期间更新或删除通知时,其通知为可以触发或忽略,具体取决于sendPastNotifications属性Timer类的使用:

  • sendPastNotifications = true -所有与之前的日期一次性通知广播开始日期,所有定期通知将以广播方式播出包括那些在开始日期之前应该发生的许多次由于无法在开始日期之后进行更新,因此将其删除。
  • sendPastNotifications = false - 具有开始前日期的通知日期被忽略;如果通知是定期的,它的通知日期会更新,但是没有通知被触发。

将sendPastNotifications标志设置为true会导致泛滥定时器启动时广播通知。 此标志的默认值
是错误的。 将此标志设置为true可确保发生的通知日期定时器停止不会丢失。 用户可以选择在计时器时接收它们即使它们不再符合它们的设定日期,它也会再次启动。

调用在已经启动的Timer上开始,或者在Timer上停止已经停止了,没有效果。 停止后,定时器处于初始状态,并可以在开始时重新启动。

11.关系服务(Relation Service)

作为代理规范的一部分,Java管理扩展(JMX)规范还定义了MBeans之间关系的模型。关系是一个用户定义的,在命名角色中的MBean之间的n元关联。 JMX规范定义用于构建表示关系的对象的类,以及它定义了关系服务,集中了代理中关系的所有操作。

所有关系都由提供有关角色信息的关系类型定义它包含诸如它们的多样性,以及满足这些MBeans的类名角色。通过关系服务,用户可以创建新的类型,然后创建,更新或删除满足这些类型的关系。关系服务也执行查询在所有关系中找到相关的MBean。

关系服务维护关系的一致性,检查所有操作和所有的MBean注销来确保一个关系总是符合它的
关系类型。如果关系不再有效,它将从关系服务中删除,尽管其成员MBean以其他方式继续存在。

11.1关系模型(The Relation Model)

一个关系由指定的角色组成,每个角色的值都是由该角色中的MBeans列表。 该列表必须符合角色信息定义相应角色的MBeans的多重性和类别。 一套一套或更多角色信息定义构成关系类型。 关系类型是a所有关联实例的模板,用于关联表示其角色的MBean。 我们使用术语关系来表示关联现有关系的特定实例MBean根据其定义关系类型中的角色。

11.1.1术语(Terminology)

JMX规范中的关系模型依赖于以下术语。 在这里,我们只定义由术语表示的概念,而不是相应的Java类。

  • role information
    描述关系中的角色之一。角色信息给出了名称的作用,它的多重性表现为一个单一的范围,即班级的名字参与此角色,读写权限和说明字符串。
  • relation type
    关系的元数据,由一组角色信息组成。 它描述了一个关系必须满足的角色,并且它可以作为一个模板创建和维护关系。
  • relation
    当前MBeans之间的关联满足给定的关系类型。 一个关系只能被创建和修改,使其所定义的角色类型总是受到尊重。 关系也可以具有属性和方法在其MBean上运行。
  • role value
    当前满足关系中给定角色的MBeans列表。 角色价值必须始终符合其相应的角色信息。
  • unresolved role
    未解决的角色是对角色非法访问操作的结果,如由其角色信息定义。 而不是由此产生的角色价值
    未解决的角色包含拒绝操作的原因。 例如,用错误的MBean类别设置角色,提供非法列表基数,或试图写只读角色都将返回一个未解决的角色。
  • support classes
    用于表示关系类型和关系实例的内部类。该支持类也暴露在简化关系的用户实现类。 用户的外部实现仍然依赖于关系服务来维护关系模型的一致性。
  • relation service
    一个可以访问和维护所有关系类型的一致性的MBean以及JMX代理中的所有关系实例。 它提供查询操作找到相关的MBeans及其在关系中的作用。 它也是唯一的来源有关关系的通知。

11.1.2关系的例子(Example of a Relation)

在本章中,我们将使用书与书之间关系的例子他们的主人。

为了在JMX规范模型中表示这种关系,我们说图书和所有者是角色。 书籍代表给定MBean的任何数量的拥有书籍类,所有者是另一个MBean类的书籍所有者。 我们可能会定义一个关系键入包含这两个角色并称之为个人图书馆,代表书籍所有权的概念。

与UML相比,下面的图表代表此示例关系建模其相应的关联。
……
FIGURE 11-1 Comparison of the Relation Models

在JMX规范模型中,关系类型是一组静态角色。 关系类型可以在运行时定义,但一旦定义,它们的角色和角色信息不能修改。 给定类型的关系实例定义每个MBean角色并在必要时为其提供操作。

11.1.3保持一致性(Maintaining Consistency)

MBean通过由关系类型定义的关系实例关联关系服务,但是MBean仍然可以通过MBean完全访问
服务器。只有注册的MBean(由它们的对象名称标识)可以是a的成关系。关系服务从不在成员MBean上运行,它只提供他们的对象名称以回应查询。

关系服务阻止无效关系类型的创建,例如,如果角色信息不一致。同样,无法建立无效关系,要么是因为关系类型不受尊重,要么是因为关系类型的对象名称成员MBean在MBean服务器中不存在。角色值的修改也受到相同的一致性检查。

从关系服务中删除关系时,其成员MBean不是通过已移除的实例更长时间的关联,但不受影响。当一个关系类型被删除,该类型的所有现有关系首先被删除。该调用者负责了解删除关系类型的后果。

因为关系仅在已注册的MBean之间定义,所以注销a成员MBean修改关系。关系服务侦听所有MBean服务器通知,用于指示何时取消注册任何关系的成员。然后将相应的MBean从其出现的任何角色值删除。如果新基数的作用与相应的关系类型不一致,该关系从关系服务中删除。

关系服务在修改关系的所有操作之后发送通知实例,创建,更新或删除。此通知提供信息关于修改,例如关系的标识符和新的角色值。该通知还表明该关系是内部还是外部定义(请参阅第174页的“外部关系”)。第171页上的图11-1中介绍的两种模型有所不同。UML协会意味着每本书只能有一个所有者。JMX规范中的关系类型仅对一组角色建模,表明这一点一个关系实例在Books中有一个拥有者MBean和任意数量的MBean角色。JMX规范关系模型只保证MBean满足其要求指定的角色,它不允许用户定义MBean可以有多少关系出现在这里。这意味着关系服务不执行相互关系一致性检查。这些是管理应用程序的责任在创建或修改关系实例时。

如果需要这种一致性水平,管理解决方案的设计者就必须这样做在使用关系服务的对象中实施必要的验证。在我们的例子,设计师需要确保同一本书MBean不是添加到多个个人图书馆关系。一种方法是通过在执行任何操作之前调用关系服务的查询方法。

11.1.4实施(Implementation)

JMX规范定义了其行为实现这一点的Java类关系模型。第170页的“术语”中定义的每个概念都有一个相应的Java类(请参见第171页的图11-2)。随着行为关系服务对象本身,这些类决定了关系服务是如何的用于管理解决方案。

本节介绍关系服务与支持之间的交互类。所有课程的操作和其他细节将进一步介绍部分。异常类是RelationException类的所有子类并只提供一个消息字符串。 API生成的文档其他类的Javadoc工具指出哪些异常是由特定引发的操作。

实际上,角色描述结构是在关系服务之外处理的,并且它们的对象直接由用户实例化(请参阅“角色描述类”第184页)。角色信息对象被分组到数组中以定义关系类型。角色对象和角色列表被实例化传递给角色值的设置者。角色结果由角色值的获取者及其角色列表和未解决的角色返回可以提取列表进行处理。

javax.management.relation
«relation service»
RelationService
RelationServiceMBean
RelationNotification
MBeanServerNotificationFilter
«relation support»
RelationType
RelationTypeSupport
Relation
RelationSupport
RelationSupportMBean
«role description»
RoleInfo
Role
RoleList
RoleUnresolved
RoleUnresolvedList
RoleResult
RoleStatus
«exception superclass»
RelationException
«relation type creation errors»
InvalidRoleInfoException
InvalidRelationTypeException
«relation creation errors»
InvalidRelationServiceException
RelationServiceNotRegistered-Exception
RoleInfoNotFoundException
InvalidRoleValueException
RelationTypeNotFoundException
InvalidRelationIdException
«relation access errors»
RelationNotFoundException
RoleNotFoundException

FIGURE 11-2 Classes of the javax.management.relation package

另一方面,关系类型和关系实例由控制关系服务维护关系模型的一致性。该JMX规范关系模型的实现提供了一个灵活的设计由此关系类型和实例可以是关系的内部或外部服务。

内部关系类型和实例由关系服务创建并且仅可以通过其操作访问。 代表类型和关系的对象内部不能被用户访问。 外部关系类型和实例是在关系服务之外实例化并在其控制下添加的对象。用户可以以任何设计的方式访问这些对象,其中包括作为注册的MBean。

11.1.4.1外部关系类型(External Relation Types)

关系服务维护一个可用于定义的关系类型列表新的关系。关系类型必须在内部创建或外部实例化并在可用于定义关系之前将其添加到关系服务中。

表示外部关系类型的对象必须实现RelationType接口。关系服务依赖于它的方法来访问角色信息每个角色由外部对象定义。请参阅“RelationTypeSupport类”有关用于定义外部关系类型的类的描述,请参阅第181页。

关系类型是不可变的,意味着一旦它们被添加到关系中服务,他们的角色定义不能被修改。如果外部关系类型暴露用于修改角色信息集的方法,它们不应该由其调用在关系服务的控制下添加实例后的用户。该这样做的结果是未定义的,关系服务中的一致性是否定的更长的保证。

使用外部关系类型的好处是角色信息可以例如,在类构造函数中静态定义。这允许预定义的类型
被快速实例化,然后添加到关系服务中。

一旦它被添加到关系服务中,就可以使用外部关系类型创造内部和外部关系。外部关系类型也是以与内部关系类型相同的方式从关系服务中删除相同的后果(请参阅第177页的“RelationService类”)

11.1.4.2对外关系(External Relations)

关系服务还维护它所控制的关系的列表。内部关系是通过关系服务创建的,只能通过其关系服务来访问方法。外部关系是由用户实例化并在其下添加的MBean关系服务的控制。它们必须在MBean服务器中注册然后才能将其添加到关系服务中。他们都可以通过关系服务以及通过MBean服务器。

外部关系对象必须实现定义该关系的Relation接口关系服务用来访问其角色值的方法。外部关系是还负责维护自己的一致性,只允许访问它的角色值由其关系类型描述。最后,外部关系必须告知任何角色值被修改时的关系服务。

关系服务对象公开检查角色信息的方法更新其内部角色值。外部关系对象必须被设计为适当时调用这些。不这样做会导致不一致的关系服务的行为之后未定义。

外部关系的主要好处是能够提供返回的方法有关关系成员的信息,甚至是角色值。因为外部关系也是一个MBean,它可以选择公开这些方法作为属性和操作。

返回到第170页上的“关系示例”,图书所有权关系可以由仅包含角色书籍的一元关系类型表示。关系
将通过外部的所有者MBean的实例来实现关系服务。这个MBean可以有一个属性,如bookCount和诸如买卖之类的操作都适用于当前的成员关系。

有关外部关系的示例,请参见第182页的“RelationSupport类”。

11.2关系服务类(Relation Service Classes)

关系服务在RelationService对象中实现,这是一个标准由RelationServiceMBean接口定义的MBean。 因此可以从管理应用程序远程访问和管理。

……
FIGURE 11-3 Relation Service Classes

关系服务MBean是通知广播者并且是唯一要发送的对象RelationNotification对象。 为了保持一致性,它还会监听MBean通过MBeanServerNotificationFilter对象的服务器通知。

11.2.1 RelationService类

关系服务提供了创建和删除关系类型和方法的方法关系实例以及访问关系中的角色。它也暴露了方法查询关系及其成员以找到相关的MBeans。

有两种方法来定义关系类型:

  • createRelationType -
    根据角色数组创建内部关系类型信息对象;关系类型通过作为a传递的名称来标识参数,并且在所有关系类型名称中必须是唯一的。
  • addRelationType -
    使外部定义的关系类型可用关系服务(请参阅第181页的“RelationType接口”)。定义关系也有两种类似的方法。每一个新的关系触发RelationNotification:
  • createRelation -
    使用给定的角色值列表创建内部关系;该关系由作为参数传递的标识符标识,并且必须是在所有关系标识符中唯一。
  • addRelation -
    将由MBean表示的外部关系放置在关系服务的控制; MBean必须先被实例化 并在MBean服务器中注册。

removeRelationType方法删除内部或外部关系类型。使用removeRelation方法将删除该类型的所有关系(请参阅第171页的“维护一致性”)。

removeRelation方法从关系服务中删除关系,这意味着它不能再被访问。成员MBeans中的角色关系继续存在。当外部关系被删除时,MBean实现它仍然可以在MBean服务器中使用。删除关系触发关系通知。

关系服务提供了访问由其标识的关系类型的方法独特的名称:getRoleInfo和getRoleInfos。

它提供了访问关系及其角色值的方法。所有角色的访问权限受限于关系类型中定义的访问模式和一致性检查,尤其是对于设置角色值:getRelationTypeName,getRole,getRoles,getAllRoles,getReferencedMBeans,setRole和setRoles。设置角色将会触发关系更新通知。

还有确定内部和外部关系的方法:

  • hasRelation - 表示是否定义了给定的关系标识符。
  • isRelation -
    获取对象名称并指示它是否已添加为与服务的外部关系。
  • isRelationMBean - 返回外部定义关系的对象名称。以下查询方法检索给定MBean所涉及的关系:
  • findReferencingRelations -
    检索给定MBean的关系引用。可以通过指定类型来限制搜索范围关系来寻找和/或预期MBean被发现的角色关系。在结果中,关系标识符被映射到角色名称列表MBean被引用(一个MBean可以在相同的几个角色中被引用关系)。
  • findAssociatedMBeans -
    检索与给定MBean关联的MBean关系服务。可以通过指定类型来限制搜索范围关系来寻找和/或预期MBean被发现的角色在关系中。在结果中,相关MBean的对象名称被映射到关系列表两者相关的标识符。

findRelationsOfType方法返回所有的关系标识符
给定关系类型的关系。

为了保持一致性,关系服务监听注销通知来自MBean服务器委托。 当有外部关系时会通知它MBean是未注册的,在这种情况下,关系被删除,或者MBean该关系的成员是未注册的(请参阅“维护一致性”第171页)。 purgeRelations方法将检查所有关系数据的一致性并删除所有不再有效的关系。

每次收到相关的撤销注册通知时,关系服务行为取决于清除标志属性:

  • 如果清除标志为真,则将调用purgeRelations方法自动。
  • 清除标志为false时,不采取任何操作,并且可能会有关系服务

关系服务还公开允许外部关系MBean的方法实现预期的行为,或通知关系服务,以便它可以保持一致性:

  • checkRoleReading和checkRoleWriting - 检查是否可以读取给定的角色并通过比较新值与角色信息进行更新。
  • sendRelationRemovalNotification,sendRoleUpdateNotification和sendRelationCreationNotification 触发给定通知事件。
  • updateRoleMap - 通知关系服务已经有角色值修改,以便它可以更新其内部数据。

11.2.2关系通知类别(RelationNotification Class)

这个类的一个实例被创建并在关系时作为通知广播创建,添加,更新或删除。它定义了两个单独的通知类型这些事件中的每一个都取决于事件是关于内部还是事件外部关系。这个类的静态字段描述了所有的通知类型字符串关系服务可以发送(参见第176页的图11-3)。

此类的方法允许侦听器检索有关事件的信息:

  • getRelationId - 返回受此事件影响的关系的标识符。
  • getRelationTypeName -返回关系的关系类型标识符受此事件影响。
  • getObjectName - 仅当所涉及的关系是一个时才返回对象名称外部定义的MBean。
  • getRoleName,getOldRoleValue,getNewRoleValue - 给予额外的有关角色更新事件的信息。
  • getMBeansToUnregister - 返回MBean的对象名称列表由于关系移除而预期未注册。

11.2.3 MBeanServerNotificationFilter类

这个类被关系服务用来只接收那些通知涉及作为角色成员或外部关系实例的MBean。 它过滤基于它们的对象名称的MBean,确保关系服务将只有接收有关MBeans的注销通知。

其方法允许关系服务在必须添加或更新过滤器时更新过滤器删除关系中的MBean或表示外部关系。

关系服务使用的过滤器实例未公开用于管理关系服务。 这个类在这里被描述,因为它是可用的一部分javax.management.relation包并可以在其他地方重用。

11.3接口和支持类(Interfaces and Support Classes)

外部关系类型和关系实例依赖于在中定义的接口下图,可以选择扩展支持类以方便使用。JMX规范的实现也可以在内部依赖这些类。
……
FIGURE 11-4 Interfaces and Support Classes

11.3.1 RelationType接口(RelationType Interface)

关系类型的任何外部表示都必须实现RelationType界面被关系服务认可。 这个接口的方法公开关系类型的名称及其角色信息(请参阅“RoleInfo类”)。

关系服务调用此接口的方法来访问关系类型名称或角色信息。 因为关系类型是不可变的,所以返回在关系类型用关系注册时,值永远不会改变服务。

实现此接口的对象的实例可以作为外部添加关系类型,使用关系服务的addRelationType方法。提供它的实现是连贯的,它可以通过关系来访问服务方式与内部关系类型相同。 事实上,内部关系类型通常由也实现此接口的对象表示

11.3.2 RelationTypeSupport类

这个类实现了RelationType接口并提供了一个通用的代表任何关系类型的机制。关系类型的名称是作为参数传递给类构造函数。

有两种方法通过一个实例定义一个特定的关系类型RelationTypeSupport类:

  • 其构造函数接受一个RoleInfo对象的数组。
  • addRoleInfo方法一次只能获取一个RoleInfo对象。

在使用此类的实例之后,不能添加角色信息在关系服务中定义一个外部关系类型。

用户也可以扩展这个类来创建自定义关系类型,而不需要重写角色信息访问方法。例如,。的构造函数子类可以确定要传递给超类的RoleInfo对象构造函数。这有效地将一个关系类型定义封装在一个可以的类中被动态下载和实例化。

关系服务的实现通常会实例化RelationTypeSupport类来定义内部关系类型,但这些对象是外部无法访问。

11.3.3关系接口(Relation Interface)

Relation界面描述了一个类的支持的操作预计实例将代表关系。 通过这个接口的方法,实现类公开了访问关系所需的所有功能。

实现Relation接口以表示外部关系的类必须装备为MBean。 该对象必须实例化并注册在它可以被添加到关系服务之前,在MBean服务器中。 那么,它可以通过关系服务或通过任何管理访问它在MBean服务器中公开的接口。

11.3.3.1指定的方法(Specified Methods)

每个关系在关系服务中通过一个唯一的关系标识符进行标识通过getRelationId方法暴露。它返回的字符串必须是在服务注册时所有关系中都是独一无二的。关系服务将拒绝添加具有重复或空标识符的外部关系。

以同样的方式,getRelationTypeName方法必须返回一个有效的关系类型名称已在关系服务中定义。外部关系实例还必须知道它将被控制的关系服务对象:这可以通过getRelationServiceName方法进行验证。这种方法返回一个假定在与MBean相同的MBean服务器中有效的对象名称外部关系实施。

关系服务使用Relation界面的其他方法进行访问一个关系在其控制下的角色。角色值可以被读取或写入单独或批量使用(请参阅第181页的“角色描述类”)。个人无法访问的角色会导致其类指示其性质的异常该错误(请参阅第157页的图11-2中的异常类)。

用于批量角色访问的方法遵循“尽力而为”策略:访问所有指示尝试角色,无法访问的角色不会阻止该操作。那些由于输入错误或由于访问而无法访问的该角色的权利将返回一个未解决的角色对象,指示该角色的性质错误(请参阅“RoleUnresolved类”一节第187页)。

getReferencedMBeans方法返回所有MBean的对象名称列表在关系中引用,每个对象名称映射到其中的角色列表MBean是一个成员。

11.3.3.2保持一致性(Maintaining Consistency)

关系服务委托维护角色一致性的责任关系对象。 通过这种方式,可以在角色执行一致性检查通过外部关系的方法访问。 但是,关系服务必须通知任何角色修改,以便它可以更新其内部数据结构并发送通知。

在访问角色时,无论是获取或设置其值,关系实例都必须验证:

  • 关系类型具有指定角色的相应角色信息。
  • 角色根据其角色信息具有适当的访问权限。
  • 为设置角色提供的角色值与该角色的信息一致关于基数和MBean类。

Relation接口的实现可以依靠checkRoleReading和提供给关系服务MBean的checkRoleWriting方法简化上述验证。

设置角色后,外部关系必须调用updateRoleMap操作关系服务,提供新老角色价值。这允许关系服务来更新其内部数据以保持一致性。

关系服务必须被告知所有新的角色值,以便它可以监听一个取消注册有关任何成员MBean的通知。当一个成员外部关系的MBean从MBean服务器(即关系)中注销服务检查它满足的角色的新基数。

如果基数不再有效并且清除标志为真,则关系服务删除此关系实例(请参阅“RelationService类”(第165页))。如果外部关系依然有效,关系服务称之为外部关系handleMBeanUnregistration方法。

在调用时,此方法将MBean从其引用的角色中移除(因为所有角色成员都必须注册MBean)。关系的保证服务将在必要时调用此方法以释放外部关系听取MBean注销本身。它也允许关系实现定义如何更新相应的角色。例如,取消注册一个给定角色的MBean可以更新其他角色。

在这种情况下,以及在暴露的方法修改角色值的任何其他情况下,实现使用自己的setRole方法或调用适当的关系服务方法,比如updateRoleMap。这是所有实现的责任Relation关系接口也维护其关系实例的一致性作为关系服务的角色价值。

11.3.4 RelationSupport Class

这个类是Relation接口的完整实现,它提供了一个通用关系机制。这个类必须用一个有效的角色列表实例化定义它将表示的关系实例。构造函数也需要一个唯一的关系标识符,以及由该满足的现有关系类型的名称给出角色列表。

事实上,RelationSupport类实现了RelationSupportMBean扩展了Relation界面。这意味着它也是一个标准的MBean管理界面暴露了所有的关系访问方法。因为外部关系必须首先在MBean服务器中注册,外部实例关系支持类可以由远程应用程序管理。

用户还可以扩展RelationSupport类以利用它的优势在开发定制的外部关系时实施。用户也可以选择扩展其MBean接口以公开其他属性或操作访问关系。此自定义仍必须保持角色的一致性访问和角色更新,但它可以使用内置的一致性机制RelationSupport类的方法。

关系服务通常实例化RelationSupport类来定义内部关系实例,但这些对象不能从外部访问。

11.4角色描述类(Role Description Classes)

关系服务访问阅读和写作关系的角色值。 JMX规范定义了用于传递角色值的类参数并将其作为结果接收。 这些类也被外部使用实现关系行为的关系MBean。

……
FIGURE 11-5 Role Description Classes

11.4.1 RoleInfo

角色信息提供角色的元数据描述。它规定:

  • 角色的名称。
  • 角色的多重性,表示为单个闭合间隔可以在该角色中引用的最小和最大数量的MBean。RoleInfo构造函数验证这是一个适当的非空间隔。
  • 所有成员必须是实例的类或接口的名称,如由MBean服务器的isInstanceOf方法确定。
  • 角色访问模式,即角色是可读的还是可写的,或两者兼而有之。

当角色信息被用作新的关系类型的参数时,它是定义角色的信息。当关系类型在关系中声明时服务,对于每个角色,该服务将验证:

  • 角色信息对象不为空。
  • 角色名称在给定关系类型的所有角色中是唯一的。关系服务不保证其他关系类型中具有相同名称的角色是相同的;这是用户的责任。

11.4.2角色类别(Role Class)

Role类的一个实例表示关系中角色的值。 它包含角色名称和引用现有MBean的对象名称列表。

角色值必须始终满足其关系类型的角色信息。 角色名称是将角色值与其定义的角色信息相关联的关键。

Role类用作两个关系的setRole方法的参数服务和关系接口。 它也是使用的列表的组成部分批量设置方法和定义初始角色值。 对于每个角色初始化或更新,关系服务验证:

  • 具有给定名称的角色在关系类型中定义。
  • 引用的MBeans的数量大于或等于最小值基数和小于或等于最大基数。
  • 每个对象名称引用一个已注册的MBean,该MBean是预期的实例类或接口。

11.4.3 RoleList Class

该类扩展java.util.ArrayList以表示一组Role对象。

RoleList类的实例用于定义关系的初始值。 什么时候调用关系服务的createRelation方法,承认a的角色0的基数可以从角色列表中省略。 关系类型的所有其他角色在初始角色列表中必须具有格式良好的角色值。

角色列表对象也被用作两者的setRoles方法的参数关系服务和关系接口。 这些方法仅为其设置角色一个有效的角色值出现在角色列表中。

最后,所有批量访问方法都会返回包含RoleList对象的结果代表成功访问的角色。

11.4.4 RoleUnresolved Class

此类的实例表示对给定的读取或写入访问不成功在关系中的作用。 它仅用于角色访问方法的返回值关系服务或实现Relation关系的对象。

该对象包含:

  • 无法访问的角色的名称
  • 为不成功的写访问提供的值
  • 尝试失败的原因,编码为整数值。 常量解码问题在第185页的图11-5中给出。

11.4.5 RoleUnresolvedList类

该类扩展java.util.ArrayList以表示一组RoleUnresolved对象。 所有批量访问方法都会返回包含RoleUnresolvedList的结果表示无法访问的角色的对象。

11.4.6 RoleResult类

RoleResult类是所有批量访问方法的返回对象关系服务和Relation界面的实现。 角色结果包含角色及其值的列表,以及未解决的角色列表和原因每个都无法访问。

作为getter的结果,角色值包含请求的当前值角色。 未解决的列表包含无法读取的角色,可能是因为角色名称无效或角色不允许阅读。

作为setter的结果,角色值包含那些角色的新值手术成功了。 未解决的列表包含不可能的角色书面,出于任何访问或一致性原因。

11.4.7 RoleStatus类

这个类包含静态字段,给出未解决角色的可能错误代码。错误代码与访问权限或一致性检查相关。该这些字段的名称标识了问题的性质,如图11-5所示第185页。

12.安全(Security)

Java管理扩展(JMX)MBean服务器可能有权访问敏感数据库信息,并可能能够执行敏感操作。 在这种情况下,它是希望控制谁可以访问那些信息以及谁可以执行这些信息操作。 JMX规范建立在标准的Java安全模型上定义控制对MBean服务器及其操作的访问权限。

本章介绍的安全检查仅在存在安全检查时执行安全经理。 也就是说,如果System.getSecurityManager()返回null,那么不执行检查。

12.1权限(Permissions)

假设读者对Java安全模型有一定的了解。一个出色的参考资料是李功的Inside Java™2平台安全性(Addison Wesley,1999年)。文档也可作为Java 2平台标准的一部分在线提供版(J2SE)标准开发工具包(SDK)。

敏感操作需要权限。在执行这样的操作之前,a执行检查以确保主叫方具有所需的权限或权限。

在程序执行过程中的任何一点,都有一组当前的执行线程持有的权限。当这样的线程调用JMX时规范操作,我们说这些是持有的权限。

执行安全检查的操作通过定义所需的权限来实现。如果持有的权限意味着需要的权限,则允许该操作。那是,至少有一个持有许可必须暗示需要的许可。

权限是一个Java对象,它是java.security.Permission的子类。这个类定义了以下方法:
public boolean implies(Permission permission);

持有的持有许可意味着需要所需的许可
held.implies(needed).
例如,要调用MBeanServerFactory.createMBeanServer,需要一个线程许可
MBeanServerPermission(“createMBeanServer”)

以下是一个线程可以容纳的一些权限,意味着需要权限:

  • MBeanServerPermission(“createMBeanServer”)
  • MBeanServerPermission(“createMBeanServer,findMBeanServer”)
  • MBeanServerPermission(“*”)
  • java.security.AllPermission()

不具有任何这些权限的线程,或任何其他权限暗示需要的一个,将无法调用createMBeanServer。 试图这样做会导致SecurityException。
JMX 1.2规范定义了三个权限:

  • MBeanServerPermission
  • MBeanTrustPermission
  • MBeanPermission

这些权限在以下各节中进行介绍。

12.1.1 MBeanServerPermission

MBeanServerPermission控制对类的静态方法的访问javax.management.MBeanServerFactory。 (请参阅“MBean Server Factory”)MBeanServerPermission由单个字符串构成参数,而权限对象的含义取决于这个字符串,如下:

  • MBeanServerPermission(“createMBeanServer”)控制对该对象的访问两个重载的方法MBeanServerFactory.createMBeanServer。持有此权限允许创建一个MBeanServer对象登记在可通过的列表中MBeanServerFactory.findMBeanServer。此权限意味着newMBeanServer权限,因此也保留它允许创建未在该列表中注册的MBeanServer对象。
  • MBeanServerPermission(“newMBeanServer”)控制对这两者的访问重载的方法MBeanServerFactory.newMBeanServer。拿着这个权限允许创建未注册的MBeanServer对象该列表可通过MBeanServerFactory.findMBeanServer访问。
  • MBeanServerPermission(“releaseMBeanServer”)控制对其的访问方法MBeanServerFactory.releaseMBeanServer。拿着这个权限允许从列表中删除MBeanServer对象通过MBeanServerFactory.findMBeanServer。
  • MBeanServerPermission(“findMBeanServer”)控制对其的访问方法MBeanServerFactory.findMBeanServer。持有此权限允许您在MBeanServerFactory的列表中找到MBeanServer对象给定其标识符,并检索列表中的所有MBeanServer对象。

为了方便定义权限,可以使用两个或多个字符串结合在一个逗号分隔的列表中。 由此产生的权限意味着所有的列表中的操作。 因此,举例来说,持有MBeanServerPermission(“newMBeanServer,findMBeanServer”)是相当于同时拥有MBeanServerPermission(“newMBeanServer”)和MBeanServerPermission(“findMBeanServer”)。

持有MBeanServerPermission(“*”)等同于持有所有上面列表中的权限。

12.1.2 MBeanPermission

MBeanPermission控制对MBeanServer对象的方法的访问由MBeanServerFactory.createMBeanServer或MBeanServerFactory.newMBeanServer。 (请参阅第7章“MBean服务器”。)

MBeanPermission使用两个字符串参数构造。 首先参数通常被称为权限的名称,但我们在这里指它作为目标。 第二个参数是权限的行为。

12.1.2.1 MBeanPermission目标(MBeanPermission Target)

MBeanPermission的目标将三条信息分组在一起,每一个都可以省略:

  • The class name。对于需要的权限,这是MBean的类名访问。某些方法不会引用类名称,在这种情况下,该类名称为空。对于持有的许可,这是空的或类名称模式。类名模式可以是一个文字类名,例如javax.management.MBeanServerDelegate或通配符javax.management。。如果类名是空的或者是星号(),那么权限涵盖任何类名。
  • The member。对于需要的许可,这是属性或名称操作被访问。对于不引用的MBeanServer方法
    属性或操作,成员为空。对于持有的权限,这可以是属性或操作的名称被访问,或者是空的或星号(*),覆盖任何属性或操作。
  • The object name。对于需要的权限,这是MBean的ObjectName被访问。 (请参阅第115页上的“ObjectName类”。)用于执行操作不引用单个MBean,它是空的。对于持有的权限,这是可以的MBean或MBean的ObjectName被访问。它可以是一个对象名称模式,它涵盖了所有具有名称的MBean匹配模式;请参阅第117页上的“图案匹配”。它也可以是空的,涵盖所有MBean,而不考虑其名称。如果持有权限中的ObjectName的域部分为空,则不是由默认域取代,因为权限可能适用于几个具有不同域的MBean服务器。

如果全部三个项目都存在,则持有的MBeanPermission只意味着需要的权限比赛。

如果所需的权限具有空类名称,则类名称与该类型无关行动被检查,所以持有的权限将匹配,无论其类名。

如果持有的权限具有空的类名称,则表示该权限涵盖任何类名称,所以无论其类名是什么,所需的权限都会匹配。

同样的规则适用于成员和对象名称。

目标中的三个项目使用以下语法编写为单个字符串:
className#member[objectName]

这三项中的任何一项都可以省略,但至少有一项必须存在。

三个项目中的任何一个都可以是字符“ - ”,表示空项目。空项目与空项目不同。举个例子,一个空的类名权限与“*”相同并表示任何类名。一个空的类名所需的权限被任何类名所隐含。所需的许可从来没有空的类名称,通常拥有的权限永远不会有空类名称。

以下是一些具有其含义的目标示例:

  • com.example.Resource#Name[com.example.main:type=resource]
    这表示对称为MBean的名称的属性或操作的访问其对象名称是com.example.main:type = resource及其类名称是com.example.Resource。
  • com.example.Resource[com.example.main:type=resource]
    com.example.Resource#*[com.example.main:type=resource]
    这两者意味着同样的事情,即访问任何属性或操作具有此对象名称和类名称的MBean。
  • #Name[com.example.main:type=resource]
    *#Name[com.example.main:type=resource]
    这些都意味着同样的事情,即访问属性或操作使用给定的对象名称调用MBean的名称,而不考虑它的类名称。
  • [com.example.main:type=resource]
    这表示使用给定的对象名称访问MBean,而不管它是什么类名称,而不管可以引用哪些属性或操作。
  • [com.example.main:*]
    这表示对具有域的对象名称的任何MBean的访问com.example.main。
  • com.example.Resource#Name
    这表示对任何MBean中名为Name的属性或操作的访问类名为com.example.Resource。
12.1.2.2 MBeanPermission操作(MBeanPermission Actions)

MBeanPermission的操作字符串表示一个或多个方法MBeanServer接口。 并非该接口中的所有方法都是可能的值操作字符串。 完整的清单如下:

  • addNotificationListener
  • getAttribute
  • getClassLoader
  • getClassLoaderFor
  • getClassLoaderRepository
  • getMBeanInfo
  • getObjectInstance
  • instantiate
  • invoke
  • isInstanceOf
  • queryMBeans
  • queryNames
  • registerMBean
  • removeNotificationListener
  • setAttribute
  • unregisterMBean

……

12.1.2.3未经检查的MBean服务器方法(Unchecked MBean Server Methods)

以下MBean服务器方法不受权限检查:

  • isRegistered - 代码总是可以发现一个给定的MBean名称存在。但是,如果没有queryMBeans或queryNames权限,找不到它不知道的MBeans的名称。此操作不受权限检查的原因是它会如果MBean存在但其类名不存在,则生成一个SecurityException由用户的权限覆盖,而它会生成一个InstanceNotFoundException如果MBean不存在,则无论如何类名由用户的权限覆盖。生成一个因此SecurityException将等同于承认MBean确实存在,所以许可检查将毫无用处。尽管可以细化这种情况下的权限检查语义,但是isRegistered方法不足以证明它的正确性。
  • getMBeanCount - 代码总是可以发现有多少MBean。再次,这被认为不足以证明定义权限的正确性
    检查它。
  • getDefaultDomain - 代码始终可以发现MBean服务器的默认值域。
12.1.2.4查询的权限检查(Permission Checking for Queries)

MBeanPermission的queryMBeans和queryNames操作允许控制其中MBean对查询可见。 queryMBeans操作继续如下:

  1. 检查持有的权限以查看它们是否暗示MBeanPermission(“ - # - [ - ]”,“queryMBeans”)如果不是,则抛出SecurityException。如果持有的权限包含任何queryMBeans权限,则这意味着这里显示的权限。只有在没有的情况下才会抛出异常查询MBeans在调用者集合中的权限。没有此检查,如果授予权限的策略被意外配置没有queryMBeans权限,那么所有的查询都会返回一个空集,没有迹象表明这个原因与安全有关。支票这里描述有助于避免这种混淆。
  2. queryMBeans的ObjectName参数,通常是对象名称模式,用于选择查询适用的一组MBean。如参数为空,所有MBean都被选中。
  3. 对于集合中的每个MBean,构造一个MBeanPermission参数是“queryMBeans”,目标参数包含类名称和MBean的对象名称。如果持有的权限不暗示这一点权限,MBean从集合中被删除。
  4. 对于剩余集合中的每个MBean,将QueryExp参数设置为queryMBean 用于决定它是否包含在最终集合中。

queryNames操作的规则与刚才陈述的完全相同,但与由queryNames替换queryMBeans。

有了这些规则,线程拥有的权限将完全控制集合线程可以通过查询看到的MBean。

所持有的权限未涵盖的MBeans是很重要的在执行查询之前从集合中删除。 换句话说,步骤3必须发生在第4步之前。否则,恶意代码可能会执行QueryExp界面将每个MBean保存在某个选定的集合中。

12.1.2.5 getDomains的权限检查(Permission Checking for getDomains)

getDomains权限筛选关于MBean名称的信息对于线程可见,与queryMBeans和queryNames类似。该
线程的持有权限应该暗示:
MBeanPermission(“ - # - [ - ]”,“getDomains”)

否则,MBeanServer.getDomains()方法会抛出一个SecurityException异常。否则,MBean服务器首先获取域的列表如果没有安全检查,并且每个域d都会返回该列表检查所持有的权限意味着:
MBeanPermission(“ - # - [d:x = x]”,“getDomains”)

否则,该域将从列表中消除。

x = x是ObjectName工作方式的工件。一个实现可以使用任何其他关键=值的可能性,而是必须有一个。

定义持有权限时,例如在安全策略文件中,getDomains权限应始终忽略ObjectName或提供在关键属性中只有一个的ObjectName模式,比如“:*”,
“com.example。”或“com.example.visible:*”。

12.1.2.6权限检查getAttributes和setAttributes(Permission Checking for getAttributes andsetAttributes)

用于查询的类似方案用于getAttributes和setAttributes操作。 getAttributes操作按如下进行:

  1. 检查持有的权限以查看它们是否暗示MBeanPermission(“className# - [objectName]”,“getAttribute”)其中className和objectName是MBean的类名和对象名被访问。如果不是,则抛出SecurityException。如果持有的权限允许MBean的任何属性上的getAttribute,则它们将暗示此处显示的许可。只有在getAttribute不允许的情况下MBean中的任何属性都会抛出异常。没有这个检查,如果调用者没有任何属性可用,则为空将返回AttributeList,但没有说明原因与安全有关的任何事情。
  2. 对于赋给getAttributes操作的列表中的每个属性attr,允许MBeanPermission(“className#attr [objectName]”,“getAttribute”)被构造。如果持有的权限不暗示此权限,则该属性从列表中删除。
  3. 然后getAttributes操作对剩余的属性起作用名单。

setAttributes操作的规则与刚才陈述的完全相同,但是将getAttribute(s)替换为setAttribute(s)。

12.1.3 MBeanTrustPermission

此许可表示签署者或代码源中的“信任”。 如果签署者或codesource被授予此权限,因此它被认为是MBeans的可信来源。只有来自可信来源的MBean才能在MBean服务器中注册。

结合MBeanPermission,MBeanTrustPermission可以实现细粒度的控制哪些MBean在MBean服务器中注册。该MBeanPermission的registerMBean操作控制哪些实体可以注册的MBean。 MBeanTrustPermission控制他们可以注册的MBean。

MBeanTrustPermission由单个字符串参数构造而成。 在这JMX规范的版本,参数可以有两个可能的值:

  • “register”
  • “*”

这两个值具有相同的含义,但是如果在将来的JMX版本中说明其他可能性,“*”将涵盖所有这些。

MBeanTrustPermission检查的详细信息如下所示例。

让c是要通过MBean服务器在MBean服务器中注册的MBean的Java类createMBean或registerMBean方法,并且让p成为构建的许可如下:
p = new MBeanTrustPermission(“register”);

然后,为了使createMBean或registerMBean成功,请执行以下操作表达必须是真实的:
c.getProtectionDomain()。暗示(p)的

否则,抛出SecurityException。

12.2策略文件示例(Policy File Examples)

以下是前面介绍的权限的一些示例可以使用标准的Java策略文件语法来授予章节。

最简单的MBean访问策略是授予所有签名者和代码库访问权限的MBean:

grant {
    permission javax.management.MBeanPermission “*”, “*”;
};

这是一个更严格的策略,它授予appl1.jar中的代码许可权获取MBean服务器的类加载器存储库:

grant codeBase “file:${user.dir}${/}appl1.jar” {
    permission javax.management.MBeanPermission ““,
    “getClassLoaderRepository”;
};

这是一个授予appl2.jar代码调用权限的策略来自任何类的MBean的isInstanceOf和getObjectInstance操作,只要它们在域“d1”中注册:

grant codeBase “file:${user.dir}${/}appl2.jar” {
    permission javax.management.MBeanPermission “[d1:*]”,
    “isInstanceOf, getObjectInstance”;
};

这是一个授予appl3.jar中代码查找MBean权限的策略服务器,并调用queryNames操作,但限制返回的设置域“JMImplementation”中的MBean:

grant codeBase “file:${user.dir}${/}appl3.jar” {
    permission javax.management.MBeanServerPermission
    “findMBeanServer”;
    permission javax.management.MBeanPermission
    “JMImplementation:*”, “queryNames”;
};

如果MBean服务器具有其他域中名称的MBean,例如一个MBean注册为“com.example.main:type = user,name = gorey”,他们会从不出现在由appl3.jar中的代码执行的queryNames的结果中。

这是一个授予appl4.jar代码创建权限的策略在任何对象名称下操作类“com.example.Foo”的MBean:

grant codeBase “file:${user.dir}${/}appl4.jar” {
    permission javax.management.MBeanPermission
    “com.example.Foo”, “instantiate, registerMBean”;
    permission javax.management.MBeanPermission
    “com.example.Foo#doIt”,
    “invoke,addNotificationListener,removeNotificationListener”;
};

第一个权限忽略对象名称。 操作或属性名称不是这两项行动所要求的。

然而,第二个权限使用“调用”操作的成员部分忽略它的“add / removeNotificationListener”操作。

这是一个允许MBeans注册的策略,不管它们来自哪里从。 (注册MBeans的线程也必须具有相应的权限MBeanPermissions。)

grant {
    permission javax.management.MBeanTrustPermission “register”;
};

这是一个只信任由“Gorey”签名的MBean的策略:

grant signedBy “Gorey” {
    permission javax.management.MBeanTrustPermission “register”;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值