快捷搜索:

使用 Java 平台管理 bean

Java™ 平台的最新版本包孕许多新的系统监视和治理特点。在本文中,三位来自 IBM Java 技巧中间团队的开拓职员一路带您开始应用这个 API。在快速概述了 java.lang.management 包之后,他们将指示您阅历大年夜量短小的实践场景,探测运行的 JVM 机能。

在 Java 2 平台 5.0 版引入的浩繁新特点中,有一个 API 可以让 Java 利用法度榜样和容许的对象监视和治理 Java 虚拟机(JVM)和虚拟机所在的本机操作系统。在本文中,将进修这个新的平台治理 API 的功能,这个 API 包孕在 java.lang.management 包中。本文将让您迅速掌握在未来的 Java 平台版本中将变得更紧张的一套新的强大年夜特点。

监视和治理 5.0 虚拟机

Java 5.0 供给了监视和治理正在运行的虚拟机的新功能。开拓职员和系统治理员能够监视 5.0 虚拟机的机能,而且对付某些属性还可以进行调优。曩昔有过应用 Java Management Extensions(JMX)履历的人都邑认识履行这些活动的机制。经由过程 JMX 技巧,一套必要节制的平台资本可以被算作简单的、定义优越的工具,工具的属性映射到给定资本的更初级特性上。

在平台治理 API 中,这些定义优越的工具叫做 MXBean。假如感觉 MXBean 听起来更像某种可能更认识的 MBean,那么就对了。这些 MXBean(或 平台 MBean)在效果上,便是封装了 5.0 平台内部特定部分的治理 bean。图 1 展示了 MXBean 在更大年夜系统中的位置:

图 1. MXBean 供给了 Java 平台的治理接口

在运行着的 5.0 兼容的虚拟机中可以发明和定制许多不合种类的功能;例如,可以获得正在应用的即时编译系统的行径细节或者得到垃圾网络办事的进展环境。

任何 Java 利用法度榜样只要得到必要的 bean 引用(应用我们本文中先容的技巧),就能使用平台 bean,然后调用适当的措施调用。在最简单的场景中,bean 客户机可以发明客户机所在的平台的信息。然则客户机还能监视完全自力的 JVM 的行径。这是有可能的,由于 MXBean 是一种 MBean,可以用 Java 5.0 可用的标准 JMX 办事远程地进行治理。

JConsole

bean 客户机的一个示例便是与 Java SE 5.0 SDK 一路供给的 JConsole 对象。这是一个图形界面,连接到 JVM 并显示 JVM 的信息。GUI 中的选项卡与 JVM 的特定方面相关;有 Memory、Threads 和 Classes 等选项卡。JConsole 对象还供给了一个整体的 Summary 选项卡,一个VM 选项卡(供给虚拟机启动时的情况信息)和一个 MBean 选项卡(用户可以用它更具体地监视平台 MBean 的状态)。

运行 JConsole

在敕令提示符下输入 jconsole 就可以启动 JConsole(假设 SDK 的 bin 目录在当前路径中)。请输入运行要监视的 JVM 的主机名,以及侦听治理哀求的端口号 —— 以及其他必要的认证细节 —— 然后点击 Connect。用默认值 localhost 和端口 0 点击 Connect,监视的是用于运行 JConsole 自己的 JVM(由于 JConsole 是一个 Java 进程)。这称作自监视模式。图 2 展示了 JConsole 的启动环境:

图 2. JConsole 启动

JConsole 在事情

到 JVM 的连接建立之后,JConsole 先显示 Summary 选项卡,如图 3 所示:

图 3. JConsole 的 Summary 选项卡

从这开始,可以选择其他选项卡。例如 Memory 选项卡,如图 4 所示,展示了 JVM 中每个内存池的应用历史:

图 4. JConsole 的 Memory 选项卡

请留意面板右上角的 Perform GC 按钮。这是应用平台 MBean 可以在 JVM 上履行的浩繁操作中的一个示例。

事情要领

到此为止所涉猎的根基内容是托管 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 当成虚拟机中真正的单体。任何光阴,只要引用哀求的是这些一次性类型,获得的回答老是同一个实例,而不论引用哀求从何而来或者在虚拟机生命周期中什么时刻发生。纵然多个客户机都在监视一个虚拟机的时刻,也相符这种环境。

MBeanServerConnection

接口 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,不论经由过程任何通信要领,着末都路由到同一个工具实例。

得到 MXBean

客户机代码造访 MXBean 有三种要领:经由过程工厂措施、经由过程平台办事器 或作为代理。

工厂措施

检索 MXBean 最简单的要领便是应用 java.lang.management.ManagementFactory 类供给的静态措施。然则,用这种要领获得的 MXBean 只能用来监视本地虚拟机。ManagementFactory 类为每种 MXBean 都定义了一个检索措施。有些措施返回 MXBean 的单一实例,有些措施返回 MXBean 实例的强类型 List。

在指定类型只有一个 MXBean 时,检索它的代码很简单。清单 1 展示了检索 ThreadMXBean 的代码:

清单 1. 检索平台惟一的 ThreadMXBean 的引用

ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();

对付可能存在多个 MXBean 实例的那些 MXBean 类型来说,存在着工厂措施,可以在 List 中返回 MXBean,如清单 2 所示:

清单 2. 检索平台上所有已知的 MemoryPoolMXBean 的强类型列表

List memPoolBeans = ManagementFactory.getMemoryPoolMXBeans();

for (MemoryPoolMXBean mpb : memPoolBeans) {

System.out.println("Memory Pool: " + mpb.getName());

}

LoggingMXBean 是 java.util.logging 包的一部分,以是,要用 LogManager 类而不是 ManagementFactory 类来造访它,如清单 3 所示:

清单 3. 从 LogManager 获得 LoggingMXBean 引用

LoggingMXBean logBean = LogManager.getLoggingMXBean();

记着,这些措施只容许造访属于本地 虚拟机的 MXBean。假如想把客户机代码扩展到能够一同处置惩罚位于同一台机械或不合结点上的远程 JVM,那么必要应用下面先容的两种措施中的一种。

经由过程平台办事器

组织代码,以对远程虚拟机的 MBean 办事器的连接进行调用,是一种可行的选择。要让这个选择成功,首先必要用关键的敕令行选项启动远程虚拟机。这些选项设置虚拟机的相关 JMX 代理侦听哀求的端口,以及起感化的安然级别。例如,以下选项启动的虚拟机,其代理会在 1234 端口上侦听,且没有安然性:

-Dcom.sun.management.jmxremote.port=1234

-Dcom.sun.management.jmxremote.authenticate=false

-Dcom.sun.management.jmxremote.ssl=false

本文后面的 安然性 一节将先容对虚拟机的安然造访。

有了远程代理侦听,就可以应用清单 4 中的代码段得到相关 MBean 办事器连接的引用:

清单 4. 用 JMXConnectorFactory 连接不合虚拟机的 MBean 办事器

try {

// connect to a separate VM's MBeanServer, using the JMX RMI functionality

JMXServiceURL address =

new JMXServiceURL( "service:jmx:rmi:///jndi/rmi://localhost:1234/jmxrmi");

JMXConnector connector = JMXConnectorFactory.connect(address);

MBeanServerConnection mbs = connector.getMBeanServerConnection();

} catch ...

一旦检索到 MBeanServerConnection,就可以应用 JMX 措施 getAttribute()、setAttribute() 和 invoke() 操作 MXBean。这将在 经由过程平台办事器监视远程虚拟机 中先容。

作为代理

造访平台 bean API 的第三种措施与前面先容的两种措施有合营之处。像曩昔一样,必要检索到被监视虚拟机的 JMX 代理的 MBeanServerConnection。然后,经由过程应用 ManagementFactory 类的静态助手措施,客户机代码可以哀求注册到远程虚拟机的 MBean 办事器上的一个指定 MXBean 的代理实例。清单 5 展示了一个示例:

清单 5. 到远程 MBean 办事器的引用能够得到远程 MXBean 的代理

try {

ThreadMXBean threadBean = ManagementFactory.newPlatformMXBeanProxy

(mbs, ManagementFactory.THREAD_MXBEAN_NAME, ThreadMXBean.class);

} catch ...

对付所有的单体 MXBean(除了 LoggingMXBean),在 ManagementFactory 类的公共静态字段中可以获得用来进行办事器注册的完备字符串名称。例如,ThreadMXBean 的 javax.management.ObjectName 的字符串表示就保存在 THREAD_MXBEAN_NAME 字段中,而 LoggingMXBean 的注册名称则保存在 java.util.logging.LogManager 类的静态字段中。清单 6 展示了对 LoggingMXBean 代理实例的哀求:

清单 6. LoggingMXBean 的字符串名称是 java.util.logging.LogManager 类的常量

try {

LoggingMXBean logBean = ManagementFactory.newPlatformMXBeanProxy

(mbs, LogManager.LOGGING_MXBEAN_NAME, LoggingMXBean.class);

} catch ...

对付可能在虚拟机中存在不止一个实例的 MXBean 类型,工作变得略微麻烦一些。在这种环境下,首先必要用 MBeanServerConnection 得到指定类型的整个已注册 MXBean 的名称。为了方便,每个单体 MXBean 的 ObjectName 的域部分保存在 ManagementFactory 中的公共静态字段中。一旦检索到这些名称,就能用每个名称构造自力的代理实例。清单 7 展示了一个示例:

清单 7. 为属于远程虚拟机的每个 MemoryManagerMXBean 创建代理

try {

// Get the names of all the Memory Manager MXBeans in the server

Set srvMemMgrNames = mbs.queryNames(new ObjectName(

ManagementFactory.MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE + ",*"), null);

// Get a MXBean Proxy for each name returned

for (Object memMgrName : srvMemMgrNames){

// Cast Object to an ObjectName

ObjectName memMgr = (ObjectName) memMgrName;

// Call newPlatformMXBeanProxy with the complete object name

// for the specific MXBean

MemoryManagerMXBean memMgrBean =

ManagementFactory.newPlatformMXBeanProxy(

mbs, memMgr.toString(), MemoryManagerMXBean.class);

// memMgrBean is a proxy to the remote MXBean. We can use it

// just as if it was a reference to a local MXBean.

System.out.println("Memory Manager Name = " +

memMgrBean.getName());

}

} catch ...

应用 MXBean

java.lang.management 文档中列出了每个 MXBean 接口定义的操作。经由过程这些操作,用户可以治理和监视虚拟机。例如,MemoryMXBean 上的操作容许打开内存系统的具体输出、哀求垃圾网络以及检索当前堆和非堆内存池应用的内存的具体信息。以是,假如关心 Java 利用法度榜样所应用的内存数量或者盼望调剂堆的尺寸,可以轻易地用 java.lang.management API 编写治理客户机,连接到利用法度榜样并监视内存的应用环境。

类似地,ThreadMXBean 也供给了 Java 利用法度榜样挂起时会有用的功能。findMonitorDeadlockedThreads() 措施返回被它标识为逝世锁的线程的 ID。然后就可以用这些 ID 来检索线程的具体信息,包括它们的客栈跟踪、它们的状态、它们是否在履行本机代码,等等。

这个线程信息是在 ThreadInfo 类的实例中供给的,这个类是 java.lang management 包中供给的由 MXBean 用来向用户返回数据快照的三个类的中一个 —— 其他两个是 MemoryUsage 和 MemoryNotificationInfo 类。这三个类中的每个类都是一个繁杂的 数据类型,包孕用于描述特定平台性子的布局化信息。

现在来看两个示例场景,演示一下上面评论争论的观点若何改变成 Java 代码。

示例 1:经由过程 MXBean 或代理监视虚拟机

正如前面评论争论过的,MXBean 的措施既可以直接在本地 MXBean 上调用,也可以经由过程代理调用。清单 8 展示了若何应用 ThreadMXBean 的 getter 和 setter 操作。这个示例中的 threadBean 变量既可所以从本机虚拟机检索的 MXBean,也可所以从远程虚拟机检索的 MXBean 的代理。一旦获得了引用,那么对付调用者来说便是透明的。

清单 8. 获取和设置 ThreadMXBean 的值

try {

// Get the current thread count for the JVM

int threadCount = threadBean.getThreadCount();

System.out.println(" Thread Count = " + threadCount);

// enable the thread CPU time

threadBean.setThreadCpuTimeEnabled(true);

} catch ...

清单 8 中应用的 setThreadCpuTimeEnabled() 措施在 5.0 兼容的虚拟机中是可选支持的。在应用清单 9 所示的可选功能时,必要进行反省:

清单 9. 在考试测验应用可选属性之前,反省是否支持可选属性

if (threadBean.isThreadCpuTimeSupported()) {

threadBean.setThreadCpuTimeEnabled(true);

}

CompilationMXBean 类型的 getTotalCompilationTime() 措施也包孕不必在每个 5.0 兼容虚拟机实现中都必须有的功能。就像清单 9 中的 setThreadCpuTimeEnabled() 一样,也有相关的措施用来反省支持是否存在。晦气用这些检测措施的代码必要处置惩罚可选措施可能抛出的任何 java.lang.UnsupportedOperationException。

清单 10 展示了若何造访虚拟机中运行的所有线程的信息。每个线程的信息都保存在自力的专用 ThreadInfo 工具中,随后可以查询这个工具。

清单 10. 得到虚拟机中运行的所有线程的名称

try {

// Get the ids of all the existing threads

long[] threadIDs = threadBean.getAllThreadIds();

// Get the ThreadInfo object for each threadID

ThreadInfo[] threadDataset = threadBean.getThreadInfo(threadIDs);

for (ThreadInfo threadData : threadDataset) {

if (threadData != null) {

System.out.println(threadData.getThreadName());

}

}

} catch ...

记着,像 ThreadInfo、MemoryUsage 和 MemoryNotificationInfo 这样的繁杂类型中包孕的信息,仅仅是哀求调用履行的时候的系统快照。这些工具在您获得对它们的引用之后,不会动态更新。以是,假如利用法度榜样必要刷新 被治理的虚拟机上这些方面的数据,必要再做另一个调用,获得更新的 ThreadInfo 或 MemoryUsage 工具。MemoryNotificationInfo 工具在这方面略有不合,由于它们不是由治理利用法度榜样拉动的,而是在事故看护中推动的(这点 将很快具体进行评论争论)。

示例 2:经由过程平台办事器监视远程虚拟机

用 MBeanServerConnection 造访远程 JVM 的 ThreadMXBean 不像清单 1 中的示例那样直接。首先,必要 ThreadMXBean 的一个 javax.management.ObjectName 实例。可以用与 MXBean 代理工具相同的名称创建这个实例,如清单 11 所示:

清单 11. 构建 ThreadMXBean 的 ObjectName

try {

ObjectName srvThrdName = new ObjectName(ManagementFactory.THREAD_MXBEAN_NAME);

...

} catch ...

可以用 ObjectName 实例来标识特定的远程 ThreadMXBean,以调用 MBeanServerConnection 的 getAttribute()、setAttribute() 和 invoke(),如清单 12 所示:

清单 12. 将 ObjectName 用于对远程 MBean 办事器的调用

try {

// Get the current thread count for the JVM

int threadCount =

((Integer)mbs.getAttribute( srvThrdName, "ThreadCount"))。intValue();

System.out.println(" Thread Count = " + threadCount);

boolean supported =

((Boolean)mbs.getAttribute(srvThrdName, "ThreadCpuTimeSupported"))。booleanValue();

if (supported) {

mbs.setAttribute(srvThrdName,

new Attribute("ThreadCpuTimeEnabled", Boolean.TRUE));

...

}

} catch ...

清单 13 展示了经由过程 MBean 办事器连接来造访虚拟机中所有当火线程的信息。应用这种措施造访的 MXBean 返回繁杂的数据类型,这些繁杂数据类型包装在 JMX 开放类型 —— 例如 javax.management.openmbean.CompositeData 工具中。

为什么要把繁杂数据包装在中心类型中呢?记着,MXBean 可能潜在地由实际上不是用 Java 说话编写的远程利用法度榜样来治理,也有可能由这样的 Java 利用法度榜样来治理,它们不能造访所有用于描述托管资本的不合性子的繁杂类型。虽然可以安然地假定到平台 JMX 代理的连接的两端都能理解简单类型(例如 boolean、long 和 string),还可以把它们映射到各自的实现说话中的对应类型,然则要假定每个可能的治理利用法度榜样都能精确地解释 ThreadInfo 或 MemoryUsage 这样的繁杂类型,那是不现实的。像 CompositeData 这样的开放类型可以用更基础的类型来代表繁杂的(即非基础的或布局化的)数据。

假如 5.0 MXBean 的远程调用要求通报繁杂类型的实例,那么工具就被转换成等价的 CompositeData。虽然这可以让信息发送到尽可能广泛的客户,却也有不够之处:实际上能够解析 ThreadInfo 和 MemoryUsage 类型的接管方 Java 利用法度榜样仍旧必要从开放类型转换到繁杂类型。但即便这样,也不算是太麻烦的步骤,由于 java.lang.management 中定义的所有支持的繁杂数据类型,都有静态的方便措施做这件事。

在清单 13 中,threadDataset 属性包孕一组 CompositeData 工具,这些工具直接映射到 ThreadInfo 工具。对付每个线程,ThreadInfo 的静态措施 from() 被用来从 CompositeData 构建等价的 ThreadInfo 工具。可以用这个工具造访每个线程的信息。

清单 13. CompositeData 类型在收集上传输繁杂数据布局

try {

// Get the ids of all the existing threads

long[] threadIDs = (long[])mbs.getAttribute(srvThrdName, "AllThreadIds");

// Get the ThreadInfo object for each threadID. To do this we need to

// invoke the getThreadInfo method on the remote thread bean. To do

// that we need to pass the name of the method to run together with the

// argument and the argument type. It's pretty ugly we know.

CompositeData[] threadDataset =

(CompositeData[]) (mbs.invoke(srvThrdName, "getThreadInfo",

new Object[]{threadIDs}, new String[] {"[J"}));

// Recover the ThreadInfo object from each received CompositeData using

// the static helper from() method and then use it to print out the

// thread name.

for (CompositeData threadCD : threadDataset) {

ThreadInfo threadData = ThreadInfo.from(threadCD);

if (threadData != null) {

System.out.println(threadData.getThreadName());

}

}

} catch ...

API 支持

假如要开拓反省虚拟机线程状态的平台治理代码,那么可能会碰到一些有趣的行径,与我们在撰写本文时碰到的一样。这会对代码有影响么?这取决于利用法度榜样应用 5.0 版 Java 平台新机制保护代码块不受并发造访影响的程度。

5.0 中的新包 java.util.concurrent.locks 引入了 ReentrantLock 类,顾名思义,可以用它构建一个可重入锁,以保护代码的关键部分。它与现有的 synchronized 关键字的隐式锁定机制异常类似,然则有一些额外的功能,这些功能对付微调节制显式锁会异常有用。清单 14 展示了它的应用示例:

清单 14. ReentrantLock 异常简单的应用

private Lock myLock = new ReentrantLock();

...

void myMethod() {

// Acquire the lock

myLock.lock();

try {

... do work in critical section ...

} finally {

// Relinquish the lock

myLock.unlock();

}// end finally

...

}

在进入关键部分之前,调用 ReentrantLock 工具的 lock() 措施,考试测验并得到锁。只有在其他线程不拥有锁的环境下才会成功,假如其他线程拥有锁,当火线程就被壅闭。在 5.0 版 Java 平台之前,可能要用清单 15 那样的代码才能编写清单 14 的功能。(当然,现在还可以这样写,由于 synchronized 还没逾期。)

清单 15. 同步的措施

synchronized void myMethod() {

... do work in critical section ...

}

在这些简单的应用中,不会看到代码行径上的差异。然则,假如使用 ThreadMXBean 和 ThreadInfo 类型来反省您知道在运行的法度榜样中会由于进入关键部分而壅闭的线程的壅闭计数,那么结果会根据应用的壅闭措施而不合。经由过程编写一些简单的代码,此中有两个不合的线程,试图调用同一个 myMethod(),并逼迫一个线程总在另一个线程之后到达,您可以自己对这个问题进行演示。这个线程显然会被壅闭,而且该当有一个正好为 1 的壅闭计数。在 myMethod() 上应用 synchronized 关键字时,会看到与线程关联的 ThreadInfo 工具有一个大年夜于 0 的壅闭计数。然则,应用新的 ReentrantLock 要领,会看到一个为 0 的壅闭计数。可以肯定地说,跟着 ThreadMXBean 的虚拟机监视功能采纳新的并发包,我们察看到的这种行径上的差异在未来的 Java 平台版本中会被清除。

看护

MemoryMXBean 在 MXBean 之间是惟一的,由于它能够把内存应用环境以事故的要领向客户机工具动态地发送看护。对付内存应用跨越一些预设阈值的问题,即时通信的好处显而易见,由于可能是利用法度榜样级上的问题征兆,或者注解必要对虚拟机进行进一步的调剂。

MemoryMXBean 应用的看护模型来自 JMX MBean 规范,该规范与 Java 编程中应用的事故看护模型很相似。作为看护的广播者,MemoryMXBean 实现了 JMX 接口 javax.management.NotificationBroadcaster,这个相对小的接口容许 bean 注册有兴趣的相助方或取消注册。然后,每个有兴趣的相助方(工具)都必须实现 javax.management.NotificationListener 接口。这个接口只包孕一个操作,在事故发生的时刻,由发出 MXBean 的事故调用。

侦听 器可以在虚拟机生命周期的任何时刻注册(或取消注册)到 MemoryMXBean 上。看护只广播到当前 已注册的相助方。

侦听 器的处置惩罚器措施在被调用时,会接管到 javax.management.Notification 类的实例。这是 JMX 事故看护模型中的通用事故旌旗灯号类型。它被设置成容纳造成它天生的事故的相称数量的信息。对付 MemoryMXBean,今朝有两类看护:

虚拟机中的内存资本(无意偶尔叫做内存池)增长跨越了预先设置的阈值。这种事故由 MemoryNotificationInfo 常量 MEMORY_THRESHOLD_EXCEEDED 表示。

垃圾网络之后 内存资本的大年夜小跨越了预先设置的阈值。这由 MemoryNotificationInfo 常量 MEMORY_COLLECTION_THRESHOLD_EXCEEDED 表示。

在处置惩罚器措施中接管到 Notification 工具后,注册的侦听 器可以查询 Notification 的类型,根据 MemoryNotificationInfo 的两个值反省天生的字符串,从而判断启程生的事故类型。

要向侦听 器通报事故的具体信息,MemoryMXBean 会用代表 MemoryNotificationInfo 工具 javax.management.openmbean.CompositeData 的详细实例精确地设置发出的 Notification 工具的用户数据(实际上,便是广播者包孕任何想要的信息的措施)。就像在 经由过程平台办事器监视远程虚拟机 中解释的一样,在 JMX 开放数据类型中封装事故数据,可以让最广泛的侦听 器都能理解数据。

安然性

到今朝为止都还不错。现在是面对被甩在一边的紧张问题 —— 安然性 —— 的时刻了。不假如不想让谁的利用法度榜样代码造访和改动虚拟机,该怎么办?有什么选项可用么? 可以设置一些系统属性,来节制造访级别和虚拟机数据从 JMX 代理向治理客户机通报虚拟机数据的要领。这些属性分成两类:口令认证 和安然套接字层(SSL)。

应用敕令行选项

为了让 5.0 兼容的虚拟机可以被监视和治理,必要用以下敕令行选项设置平台 JMX 代理的端口号:

-Dcom.sun.management.jmxremote.port=

假如不介意谁经由过程这个端口造访虚拟机,也可以添加以下两个选项,关钳口令认证和 SSL 加密(这两项默认都是开启的):

-Dcom.sun.management.jmxremote.authenticate=false

-Dcom.sun.management.jmxremote.ssl=false

在开拓 java.lang.management 客户机代码,而且想方便地监视另一台虚拟机时,一路应用这三个选项会很方便。在临盆情况中,则必要设置口令节制或 SSL(或者两者都要设置)。

口令认证

在 5.0 SDK 的 jre/lib/management 目录中,可以找到一个叫做 jmxremote.password.template 的文件。这个文件定义了两个角色的用户名和口令。第一个是监视 角色,容许造访只读的治理函数;第二个是节制 角色,容许造访读写函数。取决于必要的造访级别,客户可以用 monitorRole 或 controlRole 用户名进行认证。为了确保只有认证的用户才能造访,必要做以下事情:

把 jmxremote.password.template 的内容拷贝到叫做 jmxremote.password 的文件中,并取消掉落文件末端定义用户名和口令部分的注释,根据必要改动口令。

改动 jmxremote.password 的许可,只让所有者能够读取和改动它。(在 UNIX 和 UNIX 类的系统上,把许可设置成 600。在 Microsoft Windows 上,请按照 “How to secure a password file on Microsoft Windows systems” 一文中的阐明操作,可以在 参考资料 中找到这篇文章的链接。)

在启动虚拟机时,用以下敕令行选项指定要应用的口令文件的位置:

-Dcom.sun.management.jmxremote.password.file=

从治理客户的角度来说,必要供给精确的用户名/口令组合来造访开启了认证的虚拟机。假如客户是 JConsole,这很简单:在初始的 Connection 选项卡中供给了用户名和口令字段。要编写向远程虚拟机供给认证细节的代码,必要把清单 16 所示的改动添加到清单 4 中供给的连接代码:

清单 16. 连接到要求用户认证的远程虚拟机

try {

// provide a valid username and password (e.g., via program arguments)

String user = "monitorRole";

String pw = "password";

// place the username and password in a string array of credentials that

// can be used when making the connection to the remote JMX agent

String[] credentials = new String[] { user, pw };

// the string array of credentials is placed in a map keyed against the

// well-defined credentials identifier string

Map props = new HashMap();

props.put("jmx.remote.credentials", credentials);

// supply the map of credentials to the connect call

JMXServiceURL address =

new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1234/jmxrmi");

JMXConnector connector = JMXConnectorFactory.connect(address, props);

// it is a trivial matter to get a reference for the MBean server

// connection to the remote agent

MBeanServerConnection mbs = connector.getMBeanServerConnection();

} catch ...

对要求认证的虚拟机供给差错的用户名或口令会造成 java.lang.SecurityException。类似地,以 monitorRole 进行认证,然后想调用读写操作 —— 例如试图哀求垃圾网络 —— 也会造成抛出 SecurityException。

应用 SSL

可以用 SSL 对从平台 JMX 代理通报到监视平台治理客户的信息进行加密。通报的数据应用公钥(非对称)加密算法加密,以是只有对应私钥的持有者才能解密数据。这就防止了数据包侦听利用法度榜样偷听通信。要应用这个特点,必要在连接的两端都设置设置设备摆设摆设 SSL,此中包括天生一对密钥和一个数字证书。详细细节越过了本文的范围,请涉猎 Greg Travis 的杰出教程 “Using JSSE for secure socket communication” 懂得更多内容(请参阅 参考资料)。

好消息是,一旦设置好了密钥对和证书,应用 SSL 时并不必要改动治理客户机代码。只要应用一些敕令行选项,就可以开启加密。首先,想要监视或治理的 Java 利用法度榜样必须用以下选项启动:

-Dcom.sun.management.jmxremote.ssl.need.client.auth=true

-Djavax.net.ssl.keyStore=

-Djavax.net.ssl.trustStore=

-Djavax.net.ssl.keyStoreType=

-Djavax.net.ssl.keyStorePassword=

-Djavax.net.ssl.trustStoreType=

-Djavax.net.ssl.trustStorePassword=

盼望与平台通信的治理客户必要用以上选项的子集启动:可以用第一和第二行。假如客户是 JConsole,可以在启动 GUI 时,用 -J 敕令行语法通报这些选项,该语法会把 Java 选项通报给 JVM。

同样,教程 “Using JSSE for secure socket communication” 可以供给这些单个选项的更多细节。

回页首

停止语

我们盼望我们已经吸引您去探求关于 Java 5.0 平台的治理 API 的更多内容。由于 Java 治理扩展的呈现为 Java 企业开拓职员和治理职员供给了监视和节制他们支配的标准化要领,以是对 Java 5.0 中 java.lang.management API 的先容,供给了对利用法度榜样运行的平台进行反省的机制。

不论是要监视本地运行的利用法度榜样的线程池照样安然地反省在 intranet 上其他位置必要留意的义务关键型法度榜样的内存应用环境,MXBean 的得到和应用都异常简单。MXBean 可以起到中间感化,让您更多地懂得代码运行的情况,既可以用非侵入性的要领探查和懂得不认识的 Java 实现的特性,也可以构建自己的检测和机能监视对象。

由于 “诊断、监视和治理” 是 Java 平台即将推出的 6.0 发行版的一个关键主题,以是这个 API 肯定会在未来的 Java 技巧中承担起更紧张的角色。

参考资料

进修

您可以参阅本文在 developerWorks 举世站点上的 英文原文

java.lang.management API:请更具体地探索完备的 API。

将jsse用于安然套接字通信 ”(Greg Travis,developerWorks,2002 年 4 月):懂得关于安然套接字设置设置设备摆设摆设的更多内容。

从黑箱到企业”(Sing Li,developerWorks,2002 年 9 月-12 月):在这个三部分的系列中懂得关于 JMX 的更多内容。

How to Secure a Password File on Microsoft Windows systems”(Sun Microsystems):进修若何在 Windows 平台上保护敏感的 Java 资本,例如 jmxremote.password 文件。

WebSphere 利用办事器信息中间:懂得 WebSphere 利用办事器版本 6 若何应用 JMX 技巧。

驯服 Tiger:John Zukowski 在 developerWorks 上的系列是转移到 Java 5 上的必读文章。

Java 技巧专区:数百篇 Java 编程各方面的文章。

得到产品和技巧

MBeanInspector:WebSphere 5 用户可以下载这个技巧,钻研注册在利用办事器上的 MBean。

评论争论

developerWorks blogs:加入 developerWorks 社区。

作者简介

May Glover Gunn 学的是物理,然则心血来潮在三年前加入了 IBM。从那今后,她就在 IBM Hursley 实验室的 Java 技巧中苦衷情,担负过各类角色。近来,她为 5.0 Java 技巧版本开拓了测试,今朝仍在从事跟涉及 Java 平台的新技巧有关的事情。

George Harley 是 IBM Hursley 实验室的高档开拓职员,在 Java 技巧中苦衷情。他已经花了 10 年光阴用各类说话专业地编写软件。业余光阴里,他也是在事情。

在加入 IBM Hursley 实验室的 Java 技巧中间系统测试团队之前,Caroline Gough 在一家小软件公司做开拓职员。她现在是高档测试师,长于压力测试和 RAS (靠得住性、可用性和可办事性)对象的应用。她测试过 IBM Java 平台 5.0 版的最新端口,现在正筹备测试未来的 Java 平台版本。

您可能还会对下面的文章感兴趣: