Java Dynamic Management Kit 4.2 Tutorial

The M-Let Loader (Java 2)

In the version of the Java Dynamic Management Kit for Java 2, the m-let loader is itself a class loader object. It extends the URLClassLoader class of the java.net package to simplify the downloading service it provides.

The m-let loader service is an instance of the MLet class in the javax.management.loading package. It is also an MBean that can be accessed remotely. It provides m-let file loading and the shortcut method seen in the version for the JDK 1.1. In addition, it inherits the behavior which lets it be used directly as a class loader, without requiring an m-let file.

We will start by demonstrating the usage of the m-let service as it would be used in an agent or in an MBean. In our example, the agent application creates an MBean server and then the m-let loader.


Example 12-8 Instantiating the MLet Class

// Parse debug properties and command line arguments.
[...]

// Instantiate the MBean server
MBeanServer server = MBeanServerFactory.createMBeanServer();
String domain = server.getDefaultDomain();

// Create a new MLet MBean and add it to the MBeanServer.
String mletClass = "javax.management.loading.MLet";
ObjectName mletName = new ObjectName(domain + ":name=" + mletClass);
server.createMBean(mletClass, mletName);

There is no special initialization that needs to be done before loading classes through an m-let file.

Loading MBeans from a URL

In this example we will only load EquilateralTriangle MBeans through the m-let file. We use the same m-let file which is shown in Example 12-2, but without the tags for the Square MBeans.

The code for downloading the MBeans specified in the m-let file is also similar. In the Java 2 version of the m-let loader, only the name of the method to call and the format of its return value is different. In this code we call the getMBeansFromURL method and analyze the result:


Example 12-9 Calling the getMBeansFromURL Method

// 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());
    }
}

The structure of the returned set is much simpler than in the case of the JDK 1.1 loader. In the JDK 1.1 version, the m-let loader handles separate class loader objects, one for each code-base it has accessed. In the Java 2 version, the m-let loader is the class loader, and it handles just a list of code-bases that it has accessed directly. You can view this list by calling the getURLs method of the m-let loader MBean.

This behavior means that the getMBeansFromURL method does not need to return the object names of class loaders it has used. Instead it just returns either the object instance of the downloaded and registered MBean or a Throwable object in case or an error or an exception. These are returned in a Set object containing as many elements as there are MLET tags in the target m-let file.

Shortcut for Loading MBeans

This behavior also simplifies any repeated loading of the classes after they have been loaded from an m-let file. Because the m-let loader has already used the code-base of the MBean, it is available to be used again. All you need to do is specify the object name of the m-let loader as the class loader when creating the MBean.

You can also load other MBeans in the same code-base, once the code-base has been accessed by a call to the getMBeansFromURL method. In our example we will just download another MBean of the EquilateralTriangle class.


Example 12-10 Reloading Classes in the M-Let Class Loader

// Create another EquilateralTriangle MBean from its class
// in the EquilateralTriangle.jar file.
String triangleClass = "EquilateralTriangle";
ObjectName triangleName = new ObjectName(
    "MLetExample:name=" + triangleClass + ",id=3");
Object triangleParams[] = {new Integer(20)};
String triangleSignature[] = {"java.lang.Integer"};

server.createMBean(triangleClass, triangleName, mletName,
                   triangleParams, triangleSignature);

Again, loading classes from known code-bases or reloading a class directly from its jar file implies that the agent or MBean programmer has some knowledge of the code-bases and jar file contents at runtime.

Loading MBeans Directly

Since the m-let loader object is a class loader, you can use it to load classes directly, without needing to define an m-let file. This is the main advantage of the Java 2 version of the m-let loader service.

Before you can load an MBean directly, you need to add the URL of its code-base to the m-let loader's internal list. Then we just use the m-let loader's object name as the class loader name when creating the MBean. Here is the code to do this in the agent example:


Example 12-11 Using the M-Let MBean as a Class Loader

// 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);

// 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);

You only need to add the URL to the m-let loader the first time you want to download a class. Once it is added, we can load it as many times as necessary by calling createMBean directly.

Since this loading mechanism doesn't use the MLET tag, the programmer must insure that either the downloaded class provides its own object name or, as in the example above, the agent provides one.

The fact that the m-let loader is also a class loader into which you can load multiple URLs brings up the issue of name spaces. If there exists two classes with the same name within the code-bases defined by the set of all URLs, the m-let loader will load one of them non-deterministically. In order to specify one of them precisely, you shouldn't add the URL of the second code-base to the m-let loader. Instead, you will have to create a second m-let loader MBean to which you can add the URL for the second version of the class. In this case, you will have one m-let MBean that can load one version of the class and another m-let MBean that can load the other.

Running the M-Let Agent Example

To run the m-let agent example for Java 2, you must have installed the Java Dynamic Management Kit for 1.2, and set your classpath accordingly. This example is located in the examplesDir/MLetAgent/ directory, see "Directories and Classpath" in the preface for details.

In our example, we have two MBeans representing geometrical shapes. Before running the example, we compile them and create a jar file for each. We also compile the agent application at the same time.


$ cd examplesDir/MLetAgent/
$ javac -classpath classpath *.java

$ jar cf Square.jar Square.class SquareMBean.class
$ rm Square.class SquareMBean.class

$ jar cf EquilateralTriangle.jar EquilateralTriangle.class \
EquilateralTriangleMBean.class
$ rm EquilateralTriangle.class EquilateralTriangleMBean.class

The agent command line requires you to specify first the URL of a jar file for directly loading the Square class, then the URL of the m-let file. We have left these files in the examples directory, but you could place them on a remote machine. With the Korn shell on the Solaris platform, you would type the following command:


$ java -classpath classpath Agent \ 
file:${PWD}/Square.jar file:${PWD}/GeometricShapes.html

In the output of the agent, you can see it create the m-let loader MBean, and then download classes to create MBeans. It starts with the direct loading of the Square class, and then loads from the HTML file which specifies two EquilateralTriangle MBeans to be loaded. Once these have been loaded, we can see the third one that is loaded through the class loader shortcut.

This agent uses the tracing mechanism, and you can select to receive the messages from the m-let loader by specifying the -DINFO_MLET property on the command line. The tracing mechanism is covered in the Java Dynamic Management Kit 4.2 Tools Reference guide and in the Javadoc API of the Trace class.

The agent then launches an HTML adaptor so that we can easily view the new MBeans. In them we can see that the values contained in the ARG tags of the m-let file were used to initialize the MBeans. Point your web browser to the following URL and click on the MBeans in the MLetExample domain: http://localhost:8082/. When you are done, type <Control-C> in the window where you launched the agent.