The Artima Developer Community
Sponsored Link

Chapter 8 of Inside the Java Virtual Machine
The Linking Model
by Bill Venners

<<  Page 18 of 20  >>

Advertisement

Example: Dynamic Extension with forName()

As an example of a Java application that performs dynamic extension with forName(), consider the EasyGreet class:

// On CD-ROM in file linking/ex7/EasyGreet.java
import com.artima.greeter.*;

public class EasyGreet {

    // Arguments to this application:
    //     args[0], args[1], ... - class names of greeters to load
    //               and invoke the greet() method on.
    //
    // All greeters must implement the com.artima.greeter.Greeter
    // interface.
    //
    static public void main(String[] args) {

        if (args.length == 0) {
            System.out.println(
                "Enter greeter class names as args.");
            return;
        }

        for (int i = 0; i < args.length; ++i) {
            try {

                // Load the greeter specified on the command line
                Class c = Class.forName(args[i]);

                // Instantiate it into a greeter object
                Object o = c.newInstance();

                // Cast the Object ref to the Greeter interface type
                // so greet() can be invoked on it
                Greeter greeter = (Greeter) o;

                // Greet the world in this greeter's special way
                greeter.greet();
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

The EasyGreet application is very similar to the Greet application from the previous example. Like Greet, EasyGreet will attempt to dynamically load and execute greeters mentioned in command line arguments. But unlike Greet, EasyGreet doesn't take as its first command line argument a path name of the directory in which the class files for the greeters are stored. All of EasyGreet's command line arguments are greeter class names. Another difference is that EasyGreeter, because it is going to use forName() to load greeters dynamically, doesn't instantiate a GreeterClassLoader. Then, where Greet invoked loadClass() on its GreeterClassLoader instance, EasyGreet invokes forName(), a static method of class Class.

EasyGreet's forName() invocation looks very similar to Greet's loadClass() invocation. Like loadClass(), forName() accepts the fully qualified name of the requested type in a String parameter. If successful in loading the type (or if the type had been loaded previously), forName(), like loadClass(), returns the Class instance that represents the type. If unsuccessful, forName(), like loadClass(), throws ClassNotFoundException. The big difference between the two approaches is that whereas loadClass() attempts to ensure the requested type is loaded into the user- defined class loader's namespace, forName() attempts to ensure the requested type is loaded into the current namespace -- the namespace of the defining class loader for the type whose method includes the forName() invocation.

Because forName() is invoked from the main() method of class EasyGreet, the class loader that forName() asks to load the requested type is EasyGreet's defining class loader. When run from Sun's Java 2 SDK version 1.2, the class loader that loads EasyGreet is the system class loader, which looks for classes on the class path. To use the class path environment variable, you can execute the EasyGreet application in the linking/ex7 directory of the CD-ROM with a command like this:

java EasyGreet Hello

If you don't specify a class path either explicitly on the command line or in an environment variable, the system loader will look in the current directory for requested types. Because the current directory (the linking/ex7 directory from the CD-ROM) doesn't contain Hello.class, the system class loader is unable to locate Hello.class. The forName() method, and in turn EasyGreet's main() method, completes abruptly with a ClassNotFoundException:

java.lang.ClassNotFoundException: Hello
	at java.net.URLClassLoader$1.run(URLClassLoader.java: 202)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java: 191)
	at java.lang.ClassLoader.loadClass(ClassLoader.java: 290)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java: 275)
	at java.lang.ClassLoader.loadClass(ClassLoader.java: 247)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java: 124)
	at EasyGreet.main(EasyGreet.java, Compiled Code)

To enable EasyGreet to find Hello.class merely requires that the greeters directory be included in a class path specified on the command line with the "-cp" option, as in:

java -cp .;greeters; EasyGreet Hello

When started with this command, the EasyGreet program prints:

Hello, world!

Like the Greet method, EasyGreet will accept multiple greeter names on the command line:

java -cp .;greeters; EasyGreet Hello Greetings Salutations HowDoYouDo
When invoked with this command, the EasyGreet application will load each of the four greeters listed and invoke their greet() methods, yielding this output:
Hello, world!
Greetings, planet!
Salutations, orb!
How do you do, globe!

The important difference that arises from Greet's use of loadClass() on GreeterClassLoader and EasyGreet's use of forName() is the namespaces into which the greeter classes get loaded. In Greet, the greeter classes get loaded into the GreeterClassLoader's namespace. In EasyGreet, the greeter classes get loaded into the system class loader's namespace.

<<  Page 18 of 20  >>


Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use