在JMX的规范中,可以将Agent layer和instrumentation layer放在被管理应用,这样可以用MBean进行本地的资源管理,如果Agent layer和instrumentation layer和被管理应用分离,用JMX的实现管理多个远程应用的情况下,则需要JMX的M-let服务下载远程的MBean来进行资源管理。JMX规范中不只提供了动态加载MBean,而且提供了远程下载MBean的方法。本文介绍一下M-let服务进行动态远程下载java class的方式。
首先要知道的是M-let Class Loader作为JMX的一个服务,也是以MBean的形式存在的,因此需要实现MLetMBean接口;为了实现该MBean的下载功能,需要继承java.net.URLClassLoader。因为M-let Class Loader是一个MBean,因此可以被JMX中的代理直接的调用,也可以被management application远程调用和管理。本文假设MletTest(继承了URLClassLoader并且实现了MLetMBean接口)作为一个M-let Class Loader,下面介绍一下M-let Class Loader的动态下载方式。
1.利用M-let文件进行远程下载
M-let文件和xml文件极为相似,在JMX规范中规定了M-let的书写结构,可以参考JMX in Action或者Sun官方的文档。例如:
- <MLET CODE=jmxbook.ch2.HelloWorld ARCHIVE=test.jar NAME=hello:type=HelloWorld>
- MLET>
achive指明了远程的jar包名,code指明了其中的M-let所要动态下载的类,Name指的是该MBean注册到MBean Server中的ObjectName的字符串。因为没有定义codebase属性(该属性定义jar文件的相对路径),所以此M-let文件需要和jar包放在同一目录。MletTest的getMBeansFromURL方法是用于M-let文件远程下载java class的方法。
- // the url_2 string is read from the command line
- echo("\tURL = " + url_2);
- Object mletParams_2[] = {url_2};
- String mletSignature_2[] = {"java.lang.String"};
- Set mbeanSet = (Set) server.invoke(mletName, "getMBeansFromURL",
- mletParams_2, mletSignature_2);
- for (Iterator i = mbeanSet.iterator(); i.hasNext(); ) {
- Object element = i.next();
- if (element instanceof ObjectInstance) {
- // Success, we display the new MBean’s name
- echo("\tOBJECT NAME =
- " + ((ObjectInstance)element).getObjectName());
- } else {
- // Failure, we display why
- echo("\tEXCEPTION = " + ((Throwable)element).getMessage());
- }
- }
在第五行利用反射调用MletTest的getMBeansFromURL方法,得到的是远程的M-let文件中所描述的Mlet元素的集合。把远程的MBean下载到服务端后,当需要在MBean Server上注册MBean的时候,需要将MletTest的ObjectName作为Class Loader来将下载的MBean注册到MBean Server。因此需要以下代码来完成:
- // Create another HelloWorld MBean from its class
- // in the test.jar file.
- String triangleClass = "HelloWorld";
- ObjectName triangleName = new ObjectName(
- "hello:type=" + triangleClass);
- Object triangleParams[] = {new Integer(20)};
- String triangleSignature[] = {"java.lang.Integer"};
- server.createMBean(triangleClass, triangleName, mletName,
- triangleParams, triangleSignature);
2.直接下载远程MBean
该方法不用定义M-let文件,直接可以下载远程的MBean,该方法通过调用MletTest的addURL方法来实现远程下载。
- // Add a new URL to the MLet class loader
- // The url_1 string is read from the command line
- Object mletParams_1[] = {url_1};
- String mletSignature_1[] = {"java.lang.String"};
- server.invoke(mletName, "addURL", mletParams_1, mletSignature_1);
在第五行利用发射调用addURL方法,将url_l所指定的远程MBean下载到服务端。但是因为不使用M-let文件,因此这里没有规定加载进来的和该MBean对应的ObjectName类,因此在服务器端建立已经下载到的MBean时,需要指定ObjectName,因此需要写:
- // Create a Square MBean from its class in the Square.jar file.
- String squareClass = "Square";
- ObjectName squareName = new ObjectName(
- "MLetExample:name=" + squareClass);
- Object squareParams[] = {new Integer(10)};
- String squareSignature[] = {"java.lang.Integer"};
- server.createMBean(squareClass, squareName, mletName,
- squareParams, squareSignature);