The Java TM Tutorial

| Start of Tutorial > Start of Trail > Start of Lesson | Search

Trail: RMI
Lesson: Using Java RMI

## Running the Example Programs

### A Note about Security

> The JDK 1.2 security model is more sophisticated than the model used for JDK 1.1. JDK 1.2 contains enhancements for finer-grained security and requires code to be granted specific permissions to be allowed to perform certain operations.

> In JDK 1.1 code in the class path is trusted and can perform any operation; downloaded code is governed by the rules of the installed security manager. If you run this example in JDK 1.2, you need to specify a policy file when you run your server and client. Here is a general policy file that allows downloaded code, from any code base, to do two things:

> - Connect to or accept connections on unprivileged ports (ports greater than 1024) on any host
> - Connect to port 80 (the port for HTTP)

> Here is the code for the general policy file:

> >     grant {
> >         permission java.net.SocketPermission "*:1024-65535",
> >             "connect,accept";
> >         permission java.net.SocketPermission "*:80", "connect";
> >     };

> If you make your code available for downloading via HTTP URLs, you should use the preceding policy file when you run this example. However, if you use file URLs instead, you can use the following policy file. Note that in Windows-style file names, the backslash character needs to be represented by two backslash characters in the policy file.

> >     grant {
> >         permission java.net.SocketPermission "*:1024-65535",
> >             "connect,accept";
> >         permission java.io.FilePermission
> >             "c:\\home\\ann\\public_html\\classes\\-", "read";
> >         permission java.io.FilePermission
> >             "c:\\home\\jones\\public_html\\classes\\-", "read";
> >     };

> This example assumes that the policy file is called `java.policy` and that it contains the appropriate permissions. If you run this example on JDK 1.1, you will not need to use a policy file, since the `RMISecurityManager` provides all of the protection you need.

### Start the Server

> Before starting the compute engine, you need to start RMI's registry, using the `rmiregistry` command. As discussed earlier, the RMI registry is a simple server-side bootstrap naming facility that allows remote clients to get a reference to a remote object. Note that before you start the `rmiregistry`, you must make sure that the shell or window in which you will run `rmiregistry` either has no `CLASSPATH` environment variable set or has a `CLASSPATH` environment variable that does not include the path to any classes, including the stubs for your remote object implementation classes, that you want downloaded to clients of your remote objects.

> If you do start the `rmiregistry` and it can find your stub classes in `CLASSPATH`, it will not remember that the loaded stub class can be loaded from your server's code base, specified by the `java.rmi.server.codebase` property when you started up your server application. Therefore, the `rmiregistry` will not convey to clients the true code base associated with the stub class and, consequently, your clients will not be able to locate and to load the stub class or other server-side classes.

> To start the registry on the server, execute the `rmiregistry` command. This command produces no output and is typically run in the background. For this example, we will start the registry on the host `zaphod`.

> > Win32 (use `javaw` if `start` is not available):

> >       unset CLASSPATH
> >       start rmiregistry

> > UNIX:

> >       unsetenv CLASSPATH
> >       rmiregistry &

> By default, the registry runs on port 1099. To start the registry on a different port, specify the port number on the command line. Do not forget to unset your `CLASSPATH`.

> > Win32:

> >       start rmiregistry 2001

> > UNIX:

> >       rmiregistry 2001 &

> Once the registry is started, you can start the server. First, you need to make sure that both the `compute.jar` file and the remote object implementation class (since that is what you are starting) are in your class path.

> > Win32:

> >       set CLASSPATH=c:\home\ann\src;c:\home\ann\public_html\classes\compute.jar

> > UNIX:

> >       setenv CLASSPATH /home/ann/src:/home/ann/public_html/classes/compute.jar

> When you start the compute engine, you need to specify, using the `java.rmi.server.codebase` property, where the server's classes will be made available. In this example the server-side classes to be made available for downloading are the `ComputeEngine`'s stub and the `Compute` and the `Task` interfaces, available in `ann`'s `public_html\classes` directory. Here, we start the compute engine server on the host `zaphod`, the same host where we started the registry.

> > Win32:

> >       java -Djava.rmi.server.codebase=file:/c:\home\ann\public_html\classes/
> >            -Djava.rmi.server.hostname=zaphod.east.sun.com
> >            -Djava.security.policy=java.policy
> >               engine.ComputeEngine

> > UNIX:

> >       java -Djava.rmi.server.codebase=http://zaphod/~ann/classes/
> >            -Djava.rmi.server.hostname=zaphod.east.sun.com
> >            -Djava.security.policy=java.policy
> >               engine.ComputeEngine

> The preceding `java` command defines several properties.

> - The `java.rmi.server.codebase` property specifies the location, a code base URL, of classes originating from this server so that class information for objects sent to other virtual machines will include the location of the class so that a receiver can load it. If the code base specifies a directory (as opposed to a JAR file), you must include the trailing slash in the code base URL.
> - The `java.rmi.server.hostname` property indicates the fully qualified host name of your server. In some networked environments a fully qualified host name is not obtainable by using the Java APIs. RMI makes a best-effort attempt to obtain the fully qualified host name. If one cannot be determined, it will fall back and use the IP address. To ensure that RMI will use a host name that is usable from potential clients, you may want to set the `java.rmi.server.hostname` property as a safety measure.
> - The `java.security.policy` property is used to specify the policy file that contains the permissions you intend to grant specific code bases.

> The `ComputeEngine`'s stub class is dynamically loaded into a client's virtual machine only when the class is not already available locally and the `java.rmi.server.codebas` e property has been set properly, to the network-accessible location of the stub class, when the server is started. Once such a stub is loaded, it will not need to be reloaded for additional references to `Com-puteEngine`'s objects.

### Start the Client

> Once the registry and the engine are running, you can start the client, specifying
> - The location where the client serves up its classes (the `Pi` class), using the `java.rmi.server.codebase` property
> - As command line arguments the host name of the server--so that the client knows where to locate the `Compute` remote object--and the number of decimal places to use in the calculation
> - The `java.security.policy` property, used to specify the policy file that contains the permissions you intend to grant specific code bases

> First, set the `CLASSPATH` to see `jones`'s client and the JAR file containing the interfaces. Then start the client on another host (one named `ford`, for example) as follows:

> > Win32:

> >       set CLASSPATH c:\home\jones\src;c:\home\jones\public_html\classes\compute.jar
> >       java -Djava.rmi.server.codebase=file:/c:\home\jones\public_html\classes/
> >            -Djava.security.policy=java.policy
> >       	client.ComputePi zaphod.east.sun.com 20

> > UNIX:

> >       setenv CLASSPATH /home/jones/src:/home/jones/public_html/classes/compute.jar
> >       java -Djava.rmi.server.codebase=http://ford/~jones/classes/
> >            -Djava.security.policy=java.policy
> >               client.ComputePi zaphod.east.sun.com 20

> Note that the class path is set on the command line so that the interpreter can find `jones`'s client and the JAR file containing the interfaces.

> After starting the client, you should see the following output on your display:

> >     3.14159265358979323846

> The following figure illustrates where the `rmiregistry`, the `ComputeEngine` server, and the `ComputePi` client obtain classes during program execution.

> When the `ComputeEngine` server binds its remote object reference in the registry, the registry downloads the `ComputeEngine_Stub`, as well as the `Compute` and the `Task` interfaces on which the stub class depends. These classes are downloaded from the `ComputeEngine`'s web server or file system, as the case may be.

> The `ComputePi` client loads the `ComputeEngine_Stub`, also from the `Compute-Engine`'s web server, as a result of the `Naming.lookup` call. Since the `ComputePi` client has both the `Compute` and the `Task` interfaces available in its class path, those classes are loaded from the class path, not the remote location.

> Finally, the `Pi` class is loaded into the `ComputeEngine`'s virtual machine when the `Pi` object is passed in the `executeTask` remote call to the `ComputeEngine` object. The `Pi` class is loaded from the client's web server.

| Start of Tutorial > Start of Trail > Start of Lesson | Search