How Java RMI Works (in 5 Pages or Less)
By: André Campeau
Java RMI (Remote Method Invocation) can be used to invoke methods
of objects in another Java Virtual Machine (JVM). The JVM can
be on the local host or another host. RMI allows the client (the
thread that actually invokes a method in the remote object) to
invoke remote methods in the server (the thread that contains
the remote object) as if the remote object were contained on the
client host, from the programmer's perspective.
What really happens is that when a client calls a method in a
remote object, instead of letting the Java runtime take care of
the call as it would for regular Java objects, the RMI runtime
system takes over and routes the call over the network to the
remote object. In essence, the RMI runtime opens a socket connection
on an anonymous port to the remote object running on the server
host. The RMI runtime (running as part of the JVM on the server
side) listens on this special port for incoming RMI requests and
invokes the requested method on the server side when one is received.
Information returned by the called method is passed back to the
client through the socket, after which the socket is closed.
None of the underlying communication is visible to the programmer.
As a programmer, one may wish to access remote objects from one
or more servers out on the network. The remote objects could,
for example, contain methods which, when invoked, return information
about the hardware or software running on the server (sound familiar?).
These remote "agent" objects may exist on many servers
on the network (here "server" refers to a network element
which contains remote objects whose methods can be accessed by
interested "clients" using RMI). So how does a client,
which may come into existence at any time, find out what remote
objects it can access on servers on the network? The answer is:
by getting the server object reference from the remote object
registry.
The remote object registry runs on the server where the remote
object exists. It contains a list of references to all remote
objects on that server that are accessible to clients through
RMI. A client may query the remote object registry (henceforth
known as the "registry") to obtain a reference to a
remote object, and set a local object's reference to that of the
remote object. For example, if the object obj
was defined in the Java client program, the registry could be
queried (by specifying the URL of the remote object) to find the
reference to the object remoteObj,
and obj could be set
to point to remoteObj.
Calls to methods in obj
would be intercepted by the RMI runtime and redirected to remoteObj
on the server using socket communication as explained previously.
Note that both obj and
remoteObj must be instances
of the same class, or more specifically, obj
must implement the interface of the class that remoteObj
is instantiated from (more on this later).
This explains how to access remote methods from a client, but
how does one set up methods on a server so that they can be accessed
remotely? Each remote object server host computer must be running
a registry. The registry may be running in the same JVM as the
remote object, or in a separate JVM. The registry is an autonomous
Java thread that responds to requests from other Java programs
on the network using socket communication. The registry listens
on port 1099 by default for incoming requests. This port can
be changed, but all clients will have to be updated accordingly.
This way, you could have more than one registry running on the
same server - a necessity if the registry is built-in to more
than one remote object on the server.
Before any objects become remotely accessible to clients, they
must be registered in the registry (a process called "binding").
Objects may only be bound in a registry on the same host. This
means that you will never need to have a registry running on a
client that is not making any of its objects remotely accessible.
If there are many servers on the network offering remote objects,
then there will be also be many registries that the client may
choose remote objects from.
The registry need only be accessed the first time that the remote
object is defined on the client. To use the previous example,
when obj is instantiated
and made to point to remoteObj,
the act of making it point to remoteObj
involves a registry query. Subsequent method calls to obj
are handled by the RMI runtime on the client, so the registry
is only used for "bootstrapping" (i.e. setting up access
to the remote object for the first time).
Because there can be more than one registry running on a host,
and there may be many hosts serving remote objects on the network,
there must be a mechanism for finding bound remote objects in
the various registries. The LocateRegistry class contains static
methods that return a reference to a registry on the current host,
current host at specified port, a specified host or at a particular
port on a specified host. Using this information, the bound remote
objects in the registry can be listed, or a reference can be obtained
for setting up a client object to access methods in a remote object.
The diagram illustrates the process of setting up and accessing a remote object.
The RMI System
The RMI system consists of three layers:
The application layer sits on top of the RMI system. The relationship
between the layers is shown in the following figure.
A remote method invocation from a client to a remote server object
travels down through the layers of the RMI system to the client-side
transport, then up through the server-side transport to the server.
A client invoking a method on a remote server object actually
makes use of a stub or proxy for the remote object as a conduit
to the remote object. A client-held reference to a remote object
is a reference to a local stub. This stub is an implementation
of the remote interfaces of the remote object and forwards invocation
requests to that server object via the remote reference layer.
The remote reference layer is responsible for carrying out the
semantics of the invocation. For example the remote reference
layer is responsible for determining whether the server is a single
object or is a replicated object requiring communications with
multiple locations. Each remote object implementation chooses
its own remote reference semantics-whether the server is a single
object or is a replicated object requiring communications with
multiple locations.
The transport is responsible for connection set-up, connection
management, and keeping track of and dispatching to remote objects
(the targets of remote calls) residing in the transport's address
space.
In order to dispatch to a remote object, the transport forwards
the remote call up to the remote reference layer. The remote reference
layer handles any server-side behavior that needs to be done before
handing off the request to the server-side skeleton. The skeleton
for a remote object makes an up-call to the remote object implementation
which carries out the actual method call.
The return value of a call is sent back through the skeleton,
remote reference layer and transport on the server side, and then
up through the transport, remote reference layer and stub on the
client side.
In case you were wondering about the broadcast/multicast capability
of a client, it is possible to implement point-to-multipoint communication
strategies. The RMI package only includes UnicastRemoteObject,
which is a class in the RMI package that is extended by the client
interface object to allow point-to-point communication. If other
strategies are desired, they would have to be developed.
REFERENCES
There's a brief explanation of how to locate remote objects in
http://chatsubo.javasoft.com/current/doc/rmi-spec/rmi-objmodel.doc.html#357
See http://chatsubo.javasoft.com/current/doc/rmi/rmiregistry.html
for a brief explanation of the remote registry script/batch file.
Some information about the remote reference layer was taken from:
http://chatsubo.javasoft.com/current/doc/rmi-spec/rmi-arch.doc.html
For information on how to get started with RMI (a quick tutorial),
see:
http://chatsubo.javasoft.com/current/doc/tutorial/getstart.doc.html
The Java RMI Specification Table of Contents can be found at:
http://chatsubo.javasoft.com/current/doc/rmi-spec/rmiTOC.doc.html
Information about the LocateRegistry class can be found at:
http://chatsubo.javasoft.com/current/doc/rmi-spec/rmi-registry.doc.html#6378
There is a brief explanation of how to locate remote objects in:
http://chatsubo.javasoft.com/current/doc/rmi-spec/rmi-objmodel.doc.html#357