ss system boundaries. Thus, a server can send an object for client-side execution, and a client, perhaps wishing to take advantage of greater computing power, can upload objects to a server for execution.
But RMI has more feathers in its cap: It sports a distributed garbage collector, preserves Java's strong security features, and takes advantage of Java's multithreaded nature for the enhanced concurrent processing of requests. Furthermore, it makes good use of Java's Object Serialization to sen
d objects across systems without resorting to more complex encoding schemes, as found in CORBA.
The RMI Layers
The figure
"RMI Architecture"
shows RMI's layered structure. An invocation appears to travel between client and server, but in reality it passes through the RMI "stack" on both systems. All remote objects (i.e., objects whose methods can be remotely invoked) are represented by stubs on the client side and by skeletons on the server side. As with other remote-procedure-call (RPC) systems, this layer is responsible for marshaling method arguments and return values into a format suitable for sending between systems. For RMI, that format is Object Serialization. Only remote objects are passed by reference; all other objects are passed by copy.
The Remote Reference layer handles the behavior of remote objects and manages the Transport layer. Its task is to provide various types of method invocation, relieving stubs and skeletons from dealing with these complexiti
es. The only type that is currently provided is point-to-point, where one object invokes another's method.
The Transport layer deals directly with the network protocols that provide the actual communications mechanism between systems. This layer sets up, manages, and monitors connections, including listening for and initiating them.
A big difference between RMI and other RPC systems is
dynamic class loading
. This mechanism lets clients and servers load classes over a network during run time. Dynamic class loading downloads not only remote object classes but also stubs, skeletons, and classes used as parameters, as well as return values in remote method invocations. For example, when a client receives an object of a class for which it has no implementation, it can download the class's bytecodes dynamically (typically from the same server).
Since security is a major concern, RMI uses the stringent applet security manager restrictions for RMI-enabled applets and provides its own securi
ty manager for applications. If no security manager is defined, RMI does not load classes from network sources at all.
Garbage collection, and freedom from the memory-allocation woes that it provides, is one of Java's strengths. RMI implements a distributed reference-counting garbage collector to keep track of remote objects. As the first reference to a remote object enters a system, a call is made back to that object's server to indicate that the object is in use, or
referenced
. When the last reference to the object is discarded, an
unreferenced
message is sent to the server, which can then safely garbage-collect the object (assuming there are no other outstanding references to it).
To deal with problems such as crashed clients and network partitions, each remote object is "leased" by clients from its server. Clients must periodically renew their leases with a server, which might otherwise assume that a client is no longer using an object.
JRMP
The Transport laye
r employs JRMP, also known as the RMI Wire Protocol, to send method invocations and associated parameters and to return values and exceptions from one Java virtual machine (JVM) to another. JRMP is a simple protocol consisting of five messages, plus an extra five for multiplexing flow control.
All JRMP sessions consist of a header followed by one or more messages. The header contains just the ASCII codes for the characters
JRMI
, the protocol version, and the "subprotocol" to be used. There are three subprotocols:
SingleOpProtocol
,
StreamProtocol
, and
MultiplexProtocol
.
SingleOpProtocol
signifies that only one message follows a header before the end of a session (i.e., the connection closes).
StreamProtocol
and
MultiplexProtocol
can transfer one or more messages. The latter is used when multiplexing calls from both client and server on a single socket, as described below.
Communicating clients and servers typically each open a socket to
the other (i.e., both systems connect and listen for connections). The client's socket typically invokes methods on server-side objects, and the server's socket calls client-side objects (e.g., callbacks). The
figure shows
a hypothetical
StreamProtocol
situation. The client sends the
Call
message to invoke a server object's method; the server then invokes this method and replies with a
Return
containing any results. Assuming that a remote object is returned, the client then sends a
DgcAck
message to let the server's garbage collector know that it has received the remote object. On another socket, the server sends a
Ping
to find out whether the client is alive, which replies with a
PingAck
.
Default applet security restrictions deny applets the right to open sockets back to any server other than their originating host; they also block any attempt to listen for socket connections. This being the case, how do clients listen for ser
ver connections?
Enter the
MultiplexProtocol
and its group of five messages:
Open
,
Close
,
CloseAck
,
Request
, and
Transmit
. They allow client and server to simulate the
StreamProtocol
's two-way communication using a single socket. In the current implementation, up to 256 virtual connections can be opened, each identified by a unique ID.
Unfortunately, connecting via a socket back to the server is not always possible for applets running behind firewalls (e.g., on a corporate intranet), which typically block any attempt to open a socket back to the Internet. Should it fail to open a connection, an RMI client wraps its method invocation inside the body of an HTTP request (which is the protocol browsers use to communicate with Web servers), and the RMI server sends any results as an HTTP response.
This workaround is a smart solution, since HTTP is a firewall-trusted protocol. Still, performance takes a hit due to the time needed to co
nvert messages to HTTP requests. In addition, no multiplexing of invocations can be accomplished, because keeping the connection open between client and server is not part of HTTP 1.0. The primary reason for
SingleOpProtocol
's existence is to encapsulate RMI through HTTP.
The Future of RMI
RMI extends Java's strengths into the realm of distributed systems. In the future, we can expect to see RMI offer replicated method invocation and possibly transport layers other than TCP/IP.
RMI has been criticized for its lack of interoperability with CORBA. To address this, JavaSoft is implementing a subset of RMI on top of IIOP, enabling Java programs to access CORBA objects via RMI. It's also working to incorporate RMI's features into IIOP. Maybe RMI will indeed become the future of object-oriented communications.
illustration_link (15 Kbytes)

The RMI layers abstract invocation calls, hiding the low-level transport mechanism.
illustration_link (10 Kbytes)

JRMP enables bidirectional communications between client and server.
Paul Clip is a Java-certified consultant working at Sapient Corp. in San Francisco. You can reach him at
paul@clip.org
.