正 文

使用 Java 平台管理 bean


www.7dspace.com  更新日期:2006-5-5 6:04:45  七度空间


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=<number>

如果不介意谁通过这个端口访问虚拟机,也可以添加以下两个选项,关闭口令认证和 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 用户名进行认证。为了确保只有认证的用户才能访问,需要做以下工作:

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

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

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

      -Dcom.sun.management.jmxremote.password.file=<file-path>    

从管理客户的角度来说,需要提供正确的用户名/口令组合来访问开启了认证的虚拟机。如果客户是 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<String, String[]> props = new HashMap<String, String[]>();
    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=<keystore-location>
-Djavax.net.ssl.trustStore=<truststore-location>
-Djavax.net.ssl.keyStoreType=<keystore-type>
-Djavax.net.ssl.keyStorePassword=<keystore-password>
-Djavax.net.ssl.trustStoreType=<truststore-type>
-Djavax.net.ssl.trustStorePassword=<truststore-password>

希望与平台通信的管理客户需要用以上选项的子集启动:可以用第一和第二行。如果客户是 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 技术中承担起更重要的角色。

5页,页码:[1] [2] [3] [4] [5] 

上一篇:WindowsXP系统宽带应用技巧
下一篇:使用XML: XSLT 2.0和XQuery对比
使用 Java 平台管理 bean 作者:May Glover Gunn, George Harley,Caroline Gough 来源:developerWorks 中国
收藏此页】【打印】【关闭
站 内 搜 索
 

热 点 导 读
特 别 推 荐