Remote Method Invocation RMI
Distributed Objects
Most of the materials in these notes were from accesses provided
by the various sources on my RMI reference page and the RMI Specs
(an amazing page that makes me realize I am biting off more than I can
chew by trying to do all of these things in one semester). Also
-
For distributed object material, in particular, you should all check out
the thousands of links
on object-oriented concepts at http://www.cetus-links.org/
- For that matter, go there now and discuss Object Technology
Distributed systems require that computations running in different address
spaces, potentially on different hosts,
be able to communicate. For a basic communication mechanism, the Java
language supports sockets, which are
flexible and sufficient for general communication. However, sockets require
the client and server to engage in
applications-level protocols to encode and decode messages for exchange, and
the design of such protocols is
cumbersome and can be error-prone.
An alternative to sockets is Remote Procedure Call (RPC), which abstracts the
communication interface to the
level of a procedure call. Instead of working directly with sockets, the
programmer has the illusion of calling a
local procedure, when in fact the arguments of the call are packaged up and
shipped off to the remote target of
the call. RPC systems encode arguments and return values using an external
data representation, such as XDR.
RPC, however, does not translate well into distributed object systems, where
communication between
program-level objects residing in different address spaces is needed.
In order to match the semantics of object
invocation, distributed object systems require remote method invocation
or RMI. In such systems, a local
surrogate (stub) object manages the invocation on a remote object.
The Java remote method invocation system was designed to
operate in the Java environment. While other RMI systems can be adapted to
handle Java objects, these systems
do not have the "seamless" integration with the Java system due to their
interoperability requirement with other
languages.
For example, CORBA presumes a heterogeneous, multilanguage
environment and thus must have a
language- neutral object model. In contrast, the Java language's RMI system
assumes the homogeneous
environment of the Java Virtual Machine, and the system can therefore take
advantage of the Java object
model whenever possible.
System Goals
The goals for supporting distributed objects in the Java language are:
- Support seamless remote invocation on objects in different virtual machines.
- Support callbacks from servers to applets.
- Integrate the distributed object model into the Java language in a natural
way while retaining most of the Java language's object semantics.
- Make differences between the distributed object model and local Java object
model apparent.
- Make writing reliable distributed applications as simple as possible.
- Preserve the safety provided by the Java runtime environment.
Underlying all these goals is a general requirement that the RMI model be both
simple (easy to use) and natural (fits well in the language).
In addition, the RMI system should allow extensions such as garbage collection
of remote objects, server replication, and the activation of persistent objects to
service an invocation. These extensions should be transparent to the client and
add minimal implementation requirements on the part of the servers that use
them. To support these extensions, the system should also support:
- Several invocation mechanisms; for example simple invocation to a single
object or invocation to an object replicated at multiple locations. The system
should also be extensible to other invocation paradigms.
- Various reference semantics for remote objects; for example live
(nonpersistent) references, persistent references, and lazy activation.
- The safe Java environment provided by security managers and class loaders.
- Distributed garbage collection of active objects.
- Capability of supporting multiple transports.
Remote Method Invocation (RMI): Technology for Distributed Java
RMI is a distributed technology that extends the pure Java
object model to the network. RMI enables objects in one Java Virtual
Machine to seamlessly invoke methods on objects in a remote Virtual
Machine.
RMI lets you distribute Java objects across
the Internet and intranets, enabling you to design and deploy
extensible systems that can be modified by dynamically adding new
behavior. RMI is the next step in RPC (Remote Procedure Call) systems,
which have progressed
from procedural to object-based to object-oriented with RMI.
RMI helps programmers create distributed Java to Java applications in which
methods of remote Java objects can be invoked from other Java Virtual Machines. RMI supports traditional distribution models - such as client/server and peer-to-peer - and enriches these models with new kinds of agent-based distributed applications.
A Java program can make a call on a remote object once it obtains a
reference to the object, either by looking it up in the simple name facility
provided by RMI, or by receiving the reference as an argument or a return
value. A client can call a remote object in a server, and that server can
also be a client of other remote objects. RMI uses Object Serialization to
pass parameters and does not truncate types, supporting true object-
oriented polymorphism.
RMI's use of Object Serialization to pass parameters to and return values
from remote methods allows a program to pass many built-in Java objects, such as vectors, hashtables and dates. RMI allows a program to exchange and
return arbitrary user-defined objects. Passing objects by value is powerful
because object behavior - and not just the data - can be sent to another
Java Virtual Machine.

The Java Distributed Object Model
In the Java distributed object model, a remote object is one whose
methods can be invoked from another Java
Virtual Machine, potentially on a different host. An object of this type is
described by one or more remote
interfaces, which are Java interfaces that declare the methods of the
remote object. A remote object implements one or more remote interfaces...
By now you should be used to the delegation model and event handling
where an object can implement multiple interfaces depending on its GUI needs
Remote method invocation (RMI) is the action of invoking a method of
a remote interface on a remote object.
Most importantly, a method invocation on a remote object has the same syntax
as a method invocation on a local object.
The Distributed and Nondistributed Models Contrasted
The Java distributed object model preserves the Java object model in the
following ways:
- A reference to a remote object can be passed as an argument or returned as a result in any method invocation (local or remote).
- A remote object can be cast to any of the set of remote interfaces supported by the implementation using the syntax for casting built into the Java programming language.
- The built-in instanceof operator can be used to test the remote interfaces supported by a remote object.
- Developers can use natural Java mechanisms for the type-checking and casting of remote objects.
- Clients of remote objects interact with remote interfaces.
The Java distributed object model extends the
Java object model in several ways:
- Clients of remote objects interact with remote interfaces, never with the implementation classes of those interfaces.
- Non-remote arguments to, and results from, a remote method invocation are passed by copy rather than by reference. This is because references to objects are only useful within a single virtual machine.
- A remote object is passed by reference, not by copying the actual remote implementation. (note object)
- The semantics of some of the methods defined by class java.lang.Object are specialized for remote objects.
- Since the failure modes of invoking remote objects are inherently more complicated than the failure modes of invoking local objects, clients must deal with additional exceptions that can occur during a remote method invocation.
The primary advantages of RMIObviously shamelessly taken from a SUN page
- Object-Oriented: RMI can pass full objects as arguments and return
values, not just predefined data types. This means that you can pass
complex types, such as a standard Java hashtable object, as a single
argument. In existing RPC systems you would have to have the client
decompose such an object into primitive data types, ship those data types,
and the recreate a hashtable on the server. RMI lets you ship objects
directly across the wire with no extra client code.
- Mobile Behavior: RMI can move behavior (class implementations) from
client to server and server to client. For example, you can define an
interface for examining employee expense reports to see whether they
conform to current company policy. When an expense report is created, an
object that implements that interface can be fetched by the client from the
server. When the policies change, the server will start returning a
different implementation of that interface that uses the new policies. The
constraints will therefore be checked on the client side-providing faster
feedback to the user and less load on the server-without installing any new
software on user's system. This gives you maximal flexibility, since
changing policies requires you to write only one new Java class and install
it once on the server host.
- Design Patterns: Passing objects lets you use the full power of
object-oriented technology in distributed computing, such as two- and
three-tier systems. When you can pass behavior, you can use object-oriented
design patterns in your solutions. All object-oriented design patterns rely
upon different behaviors for their power; without passing complete
objects-both implementations and type-the benefits provided by the design
patterns movement are lost.
- Safe and Secure: RMI uses built-in Java security mechanisms that
allow your system to be safe when users downloading implementations. RMI
uses the security manager defined to protect systems from hostile applets
to protect your systems and network from potentially hostile downloaded
code. In severe cases, a server can refuse to download any implementations
at all.
- Easy to Write/Easy to Use: RMI makes it simple to write remote Java
servers and Java clients that access those servers. A remote interface is
an actual Java interface. A server has roughly three lines of code to
declare itself a server, and otherwise is like any other Java object. This
simplicity makes it easy to write servers for full-scale distributed object
systems quickly, and to rapidly bring up prototypes and early versions of
software for testing and evaluation. And because RMI programs are easy to
write they are also easy to maintain.
- Connects to Existing/Legacy Systems: RMI interacts with existing
systems through Java's native method interface JNI. Using RMI and JNI you
can write your client in Java and use your existing server implementation.
(see javah ) When you use RMI/JNI to connect to existing servers you can rewrite any
parts of your server in Java when you choose to, and get the full benefits
of Java in the new code. Similarly, RMI interacts with existing relational
databases using JDBC without modifying existing non-Java source that uses
the databases.
- Write Once, Run Anywhere: RMI is part of Java's "Write Once, Run
Anywhere" approach. Any RMI based system is 100% portable to any Java
Virtual Machine, as is an RMI/JDBC system. If you use RMI/JNI to interact
with an existing system, the code written using JNI will compile and run
with any Java virtual machine.
- Distributed Garbage Collection: RMI uses its distributed garbage
collection feature to collect remote server objects that are no longer
referenced by any clients in the network. Analogous to garbage collection
inside a Java Virtual Machine, distributed garbage collection lets you
define server objects as needed, knowing that they will be removed when
they no longer need to be accessible by clients.
- Parallel Computing: RMI is multi-threaded, allowing your servers to
exploit Java threads for better concurrent processing of client requests.
- The Java Distributed Computing Solution: RMI is part of the core
Java platform starting with JDK 1.1, so it exists on every 1.1 Java
Virtual Machine. All RMI systems talk the same public protocol, so all Java
systems can talk to each other directly, without any protocol translation
overhead.
Remote Method Invocation Architecture Overview
The RMI system consists of three layers:
The Remote Method Invocation Three-Layer Architecture
- Stub/Skeletons
Client-side stubs
(proxies) and server-side skeletons.
- Remote Reference Layer
Reference/invocation behavior (e.g.,
unicast, multicast).
- Transport
Connection set up and
management and remote object
tracking.
Because the boundary at each
layer is defined by a specific interface and protocol, each layer is independent of the next, and can be replaced by an alternate
implementation without affecting the other layers in the system.
Transparent transmission of objects from one address space to another is
achieved through Object Serialization, a technique that supports the
encoding of objects - and the objects they can reach - into a stream of bytes. Object Serialization also supports the complementary reconstruction of the object graph from the stream.
Another technique - known as dynamic stub loading - is used to support
client-side stubs that implement the same set of remote interfaces as a
remote object. When a stub of the exact type is not already available to the
client, dynamic stub loading allows the client to use the Java Platform's built-in operators for casting and type-checking.

Java RMI Architecture
RMI is a layer on top of the Java Virtual Machine which leverages the Java
system's built-in garbage collection, security and class-loading
mechanisms. The application layer sits on top of the RMI system.
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. Next, the invocation is sent - potentially via network communication - to the server-side transport, where it then travels up through the transport to the server.
A client invoking a method on a remote server object actually uses a stub
or proxy as a conduit to the remote object. A client-held reference to a
remote object is a reference to a local stub, which is an implementation of
the remote interfaces of the object and which forwards invocation requests
to it via the remote reference layer. Stubs are generated using the rmic
compiler
The remote reference layer in the RMI system separates out the specific
remote reference behavior from the client stub. Any call initiated by the
stub is done directly through the reference layer, enabling appropriate reference semantics to be carried out. For example, if a remote reference had the behavior of connection retry, it would attempt to establish the retry connection on behalf of the stub. When the connection initiation succeeded, the reference layer would forward the marshaling of arguments and send the RMI call to the underlying transport for that reference type.
Another kind of remote reference could be one that carries out multicast to a set of replicas for a remote object (multiplexing ... multicasting?). The stub for the remote object would call through the remote reference layer, which in turn would communicate
to the replica set via the transport. The reference layer provides the abstraction necessary for multiple reference semantics to be carried out without changing a stub's form. A stub simply instructs the layer beneath it to initiate a call, marshals and unmarshals parameters, and returns the result.
Also handled by the remote reference layer are the reference semantics for the server. The remote reference
layer, for example, abstracts the different ways of referring to objects that are implemented in (a) servers that
are always running on some machine, and (b) servers that are run only when some method invocation is made
on them (activation). At the layers above the remote reference layer, these differences are not seen.
The transport layer is responsible for connection setup, 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 occur 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.
The stub/skeleton layer is the interface between the application layer and the
rest of the RMI system. This layer does not deal with specifics of any transport,
but transmits data to the remote reference layer via the abstraction of marshal
streams. Marshal streams employ a mechanism called object serialization which
enables Java objects to be transmitted between address spaces. Objects
transmitted using the object serialization system are passed by copy to the
remote address space, unless they are remote objects, in which case they are
passed by reference.
A stub for a remote object is the client-side proxy for the remote object. Such a
stub implements all the interfaces that are supported by the remote object
implementation. A client-side stub is responsible for:
- Initiating a call to the remote object (by calling the remote reference layer).
- Marshaling arguments to a marshal stream (obtained from the remote
reference layer).
- Informing the remote reference layer that the call should be invoked.
Upon return:
- Unmarshaling the return value or exception from a marshal stream.
- Informing the remote reference layer that the call is complete.
A skeleton for a remote object is a server-side entity that contains a method
which dispatches calls to the actual remote object implementation. The
skeleton is responsible for:
- Unmarshaling arguments from the marshal stream.
- Making the up-call to the actual remote object implementation.
- Marshaling the return value of the call or an exception (if one occurred) onto
the marshal stream.
The appropriate stub and skeleton classes are determined at run time and are
dynamically loaded as needed, as described in
the next notes. Stubs and skeletons are generated using the rmic compiler J2SE 5.0 .
The remote reference layer deals with the lower-level transport interface. This
layer is also responsible for carrying out a specific remote reference protocol
which is independent of the client stubs and server skeletons.
Each remote object implementation chooses its own remote reference subclass
that operates on its behalf. Various invocation protocols can be carried out at
this layer. Examples are:
- Unicast point-to-point invocation.
- Invocation to replicated object groups.
- Support for a specific replication strategy.
- Support for a persistent reference to the remote object (enabling activation
of the remote object).
- Reconnection strategies (if remote object becomes inaccessible).
The remote reference layer has two cooperating components: the client-side
and the server-side components. The client-side component contains
information specific to the remote server (or servers, if the remote reference is
to a replicated object) and communicates via the transport to the server-side
component. During each method invocation, the client and server-side
components perform the specific remote reference semantics. For example, if a
remote object is part of a replicated object, the client-side component can
forward the invocation to each replica rather than just a single remote object.
In a corresponding manner, the server-side component implements the specific
remote reference semantics prior to delivering a remote method invocation to
the skeleton. This component, for example, would handle ensuring atomic
multicast delivery by communicating with other servers in a replica group
(note that multicast delivery is not part of the JDK 1.1 release of RMI).
The remote reference layer transmits data to the transport layer via the
abstraction of a stream-oriented connection. The transport takes care of the
implementation details of connections. Although connections present a
streams-based interface, a connectionless transport can be implemented
beneath the abstraction.
In general, the transport layer of the RMI system is responsible for:
- Setting up connections to remote address spaces.
- Managing connections.
- Monitoring connection "liveness."
- Listening for incoming calls.
- Maintaining a table of remote objects that reside in the address space.
- Setting up a connection for an incoming call.
- Locating the dispatcher for the target of the remote call and passing the
connection to this dispatcher.
The concrete representation of a remote object reference consists of an endpoint
and an object identifier. This representation is called a live reference. Given a
live reference for a remote object, a transport can use the endpoint to set up a
connection to the address space in which the remote object resides. On the
server side, the transport uses the object identifier to look up the target of the
remote call.
The transport for the RMI system consists of four basic abstractions:
- An endpoint is the abstraction used to denote an address space or Java
virtual machine. In the implementation, an endpoint can be mapped to its
transport. That is, given an endpoint, a specific transport instance can be
obtained.
- A channel is the abstraction for a conduit between two address spaces. As
such, it is responsible for managing connections between the local address
space and the remote address space for which it is a channel.
- A connection is the abstraction for transferring data (performing
input/output).
- The transport abstraction manages channels. Each channel is a virtual
connection between two address spaces. Within a transport, only one
channel exists per pair of address spaces (the local address space and a
remote address space). Given an endpoint to a remote address space, a
transport sets up a channel to that address space. The transport abstraction
is also responsible for accepting calls on incoming connections to the
address space, setting up a connection object for the call, and dispatching to
higher layers in the system.
A transport defines what the concrete representation of an endpoint is, so
multiple transport implementations may exist. The design and implementation
also supports multiple transports per address space, so both TCP and UDP can
be supported in the same virtual machine. Note that the RMI transport
interfaces are only available to the virtual machine implementation and are
not available directly to the application.
Thread Usage in Remote Method Invocations
A method dispatched by the RMI runtime to a remote object implementation (a
server) may or may not execute in a separate thread. Some calls originating
from the same client virtual machine will execute in the same thread; some will
execute in different threads. Calls originating from different client virtual
machines will execute in different threads. Other than this last case of different
client virtual machines, the RMI runtime makes no guarantees with respect to
mapping remote object invocations to threads.
Simple Examples Getting feet wet
You should all have these available if you downloaded docs with
the JDK. The local Getting Started Using RMI page walks us through setting
the HelloWorld RMI applet up.
- From the JDK: JAVA_HOME/docs/guide/rmi/examples/hello
- From the JDK: JAVA_HOME/docs/guide/rmi/examples/stock
However since we cannot run the Applet using RMI for security reasons, I suggest the application version below (besides, things have changed since the first version):
RMI index and the SUN location for the Getting Started tutorial for JDK 5.0 ( local ) as well as tutorial trail continued
the RMI Specs page has another example of setting everything up.