RMI
Abridged Java Remote Method Invocation Specification

extra references: The JDK 1.2.2 Documentation
latest revision: minor Nov 6 / 2000                                                                           Edit by  P.Komisar


Remote Method Invocation (RMI) is the action of invoking a method (of a remote interface)
on a remote object. A remote object is one whose methods can be invoked from another Java
Virtual Machine, A method invocation on a remote object has the same syntax as a method
invocation on a local object.

Distributed systems require that computations running in different address spaces, potentially on
different hosts, be able to communicate. In such systems, (RMI provides) a local surrogate (stub)
object which manages the invocation on a remote object.

RMI applications are often comprised of two separate programs: a server and a client. A typical
server application creates a number of remote objects, makes references to those remote objects
accessible, and waits for clients to invoke methods on those remote objects. A typical client
applications gets a remote reference to one or more remote objects in the server and then invokes
methods on them. RMI provides the mechanism by  which the server and the client communicate
and pass information back and forth. Such an applications is sometimes referred to as a
distributed object application.

Applications can use one of two mechanisms to obtain references to remote objects:

(1) register its remote objects with RMI's simple naming facility, the rmiregistry, or
(2) the application can pass and return remote object references as part of its normal operation.
 

The java.rmi.Remote Interface                                                                          [2.4.1]

In RMI, a remote interface declares a set of methods that may be invoked from a remote Java
Virtual Machine such as to satisfy the following requirements:

  1)  A remote interface must extend, the interface java.rmi.Remote, (directly or by extension)
  2)  A remote method declaration must include the exception java.rmi.RemoteException(or a parent)
  3)  In a remote method declaration, a remote object (declared as a parameter or return value) must
       be declared as the remote interface, not the implementation class of that interface.

The parent, java.rmi.Remote, is a marker interface that defines no methods.

 public interface Remote{ }
 


 The RemoteException Class                                                                                       [2.4.2]

java.rmi.RemoteException is the exception superclass the RMI runtime may throw during a
remote invocation


The RemoteObject Class and its Subclasses                                                     [2.4.3]
 
 
                                                      java.lang.Object
                                                                     |
                                               java.rmi.server.RemoteObject
                                                                     |
                                               java.rmi.server.RemoteServer
                                                                    |
        java.rmi.activation.Activatable -- +--java.rmi.server.UnicastRemoteObject
.

 

RMI server functions are provided by java.rmi.server.RemoteObject and its subclasses,
RemoteServer& UnicastRemoteObject, and java.rmi.activation.Activatable. RemoteObject
provides implementations for the java.lang.Object methods, hashCode, equals, and toString,
in a way sensible for remote objects. The methods needed to create and export remote objects,
(make them available to remote clients), are provided by the classes UnicastRemoteObject and Activatable.UnicastRemoteObject class defines a simple (unicast) remote object whose references
are valid only while the server process is alive. The class Activatable is abstract, defining an
activatable remote object that starts executing when it's remote methods are invoked. Activatable
can shut itself down when necessary.

The general rules for a class that implements a remote interface are as follows: The class

 (1) usually extends java.rmi.server.UnicastRemoteObject inheriting the remote behavior
      of RemoteObject and RemoteServer.
(2) can implement any number of remote interfaces.
(3) can extend another remote implementation class.
(4) can define methods that do not appear in the remote interface, for local but not remote use.

 Parameter Passing in Remote Method Invocation                                          [2.6]

An argument to, or a return value from, a remote object can be any serializable Java object.
This includes Java  primitive types, remote Java objects, (RMI types)and non-remote
java objects (those implementing the java.io.Serializable interface). Classes, for parameters
or return values, that are not available locally are downloaded dynamically by the RMI system.

Passing Non-remote Objects                                                                            [2.6.1]

A non-remote object, (passed as a parameter of a remote method invocation or returned as
a result), is passed by copy, that is, the object is serialized and sent using the java's object
serialization mechanism.

Passing Remote Objects                                                                                    [2.6.2]

When passing a remote object as a parameter or return value in a remote method call, the stub
for the remote object is passed. A remote object passed as a parameter can only implement
remote interfaces.

Class Annotation                                                                                                [2.6.4]

When an object is sent from one VM to another in a remote method call, the RMI system
annotates the class descriptor in the call stream with information (the URL) of the class
so that the class can be loaded at the receiver. It is a requirement that classes be downloaded on
demand during remote method invocation.   // this is where an HTTP or FTP file service comes in

Parameter Transmission                                                                                     [2.6.5]

Parameters are written to a subclass of the java.io.ObjectOutputStream to serialize parameters
to the destination of the remote call. The subclass calls the replaceObject method for each object
written to the stream via the writeObject method (that includes objects referenced by those objects
that are written). The replaceObject method of RMI's subclass of ObjectOutputStream returns
the following:

(1) if the object passed to replaceObject is an instance of java.rmi.Remote, then it returns the
     remote object stub, via a call to the method RemoteObject.toStub.
(2) if the object passed to replaceObject is not an instance of java.rmi.Remote, then the object is
     simply returned. RMI's subclass of ObjectOutputStream also implements the annotateClass
     method that annotates the call stream with the location of the class so that it can be
     downloaded at the receiver.

Since parameters are written to a single ObjectOutputStream, references that refer to the same
object at the caller will refer to the same copy of the object at the receiver. At the receiver,
parameters are read by a single ObjectInputStream.

Locating Remote Objects                                                                                            [2.7]

A simple bootstrap name server is provided for storing named references to remote objects.
A remote object reference can be stored using url-based methods of the class, java.rmi.Naming.
The Naming class provides Uniform Resource Locator, based methods to lookup, bind, rebind,
unbind, and list, the name-object pairings maintained on a particular host and port.

Stubs and Skeletons                                                                                              [3.1]

RMI uses a mechanism, (employed in  RPC), for communicating with remote objects: Stubs and
Skeletons. A stub for a remote object acts as a client's local representative or proxy for the
remote object. The caller invokes a method on the local stub which is reponsible for carrying out
the method call on the remote object. In RMI, a stub for a remote object implements the same set
of remote interfaces that a remote object implements.

When a stub's method is invoked, the stub:  // does the  client side socket / stream / write & read

    (1)  initiates a connection with the remote VM containing the remote object.
    (2)  writes and transmits (marshals) parameters to the remote VM
    (3)  waits for the result of the method invocation
    (4)  reads (unmarshals) the return (value or exception)
    (5)  returns the value to the caller

The stub hides the serialization of parameters and the network-level communication in order to
present a simple invocation mechanism to the caller. In the remote VM, each remote object may
have a corresponding skeleton (in an all-JDK1.2.x environment, skeletons are not required.*) .
The skeleton is responsible for dispatching the call to the actual remote object implementation.

A skeleton receiving an incoming method invocation it does:

     (1) reads (unmarshals) the parameters for the remote method
      (2) invokes the method on the actual remote object implementation
      (3) writes and transmits (marshals) the result (return value or exception) to the caller
 
 
* Note:
 New in JDK1.2, an additional stub protocol eliminates the need for skeletons. Instead, generic code 
 is used to carry out the skeleton's duties. Stubs and skeletons are generated by the rmic compiler

Thread Usage in Remote Method Invocations                                                  [3.2]

Since remote method invocation on the same remote object may execute concurrently, a remote
object implementation needs to make sure its implementation is thread-safe.   // synchronized

Garbage Collection of Remote Objects                                                              [3.3]

When a remote object is not referenced by any client, the RMI runtime refers to it using a weak
reference. The weak reference allows the Java virtual machine's garbage collector to discard the
object if no other local references to the object exist. As long as a local reference to a remote object
exists, it cannot be garbage-collected and it can be passed in remote calls or returned to clients.

 Dynamic Class Loading                                                                                      [3.4]
 

public abstract class ClassLoader extends Object


// Here are the first few lines of the the JDK1.2.2 API 's description of abstract ClassLoader.
// RMI has it's own class  RMIClassLoader, which extends Object and is specialized to load 
// from urls over networks. 
 ClassLoader is an abstract class. A class loader is an object that is responsible for loading
 classes. Given the name of a class, it should attempt to locate or generate data that constitutes 
 a definition for  the class. A typical strategy is to transform the name into a file name and then 
 read a "class file" of that name from a file system. 


public abstract class RMISocketFactory extends Object


// The description from the API of RMISocketFactory shows the different strategies it will
// take to make a connection despite a firewall
 The RMISocketFactory is used by the RMI runtime in order to obtain client and server sockets
 for RMI calls. The default implementation of the socket factory performs a three-tiered approach 
 to creating client sockets. First, a direct socket connection to the remote VM is attempted. If that 
 fails (due to a firewall), the runtime uses HTTP with the explicit port number of the server. If the 
 firewall does not allow this type of communication, then HTTP to a cgi-bin script on the server is 
 used to POST the RMI call. An application may set the source of sockets for RMI. In this case, 
 the application is responsible for offering up sockets that will penetrate a firewall.
.

RMI allows parameters, return values and exceptions passed in RMI calls to be any object that is
serializable. RMI uses the object serialization mechanism to transmit data from one virtual machine
to another and also annotates the call stream with the appropriate location information so that the
class definition files can be loaded at the receiver.

When parameters and return values for a remote method invocation are unmarshaled to become
'live objects' in the receiving VM, class definitions are required for all of the types of objects in
the stream.

The unmarshalling process

(1) first attempts to resolve classes by name in its local class loading context (of the current thread).

(2) RMI also provides a facility for dynamically loading the class definitions for the actual types
      of objects passed as parameters and return values for remote method invocations from network
      locations specified by the transmitting endpoint. This includes the dynamic downloading of remote
      stub classes corresponding to particular remote object implementation classes (and used to contain
      remote references) as well as any other type that is passed by value in RMI calls.

For dynamic class loading, the RMI runtime uses special subclasses of ObjectOutputStream
and ObjectInputStream to marshal and unmarshal, RMI parameters and return values. These
subclasses override the annotateClass method of ObjectOutputStream and the resolveClass
method of ObjectInputStream to communicate information about where to locate class files
containing the definitions for classes corresponding to the class descriptors in the stream.

For every class descriptor written to an RMI marshal stream, the annotateClass method adds
to the stream the result of calling java.rmi.server.RMIClassLoader.getClassAnnotation for
the class object, which may be null or may be a String object representing the codebase URL
path (a space-separated list of URLs) from which the remote endpoint should download the
class definition file for the given class.

For every class descriptor read from an RMI marshal stream, the resolveClass method reads a
single object from the stream.
If the object is a String (and the java.rmi.server.useCodebaseOnly property value is not true),
then resolveClass returns the result of calling RMIClassLoader.loadClass with the annotated
String object as the first parameter and the name of the desired class in the class descriptor as the
second parameter. Otherwise, resolveClass returns the result of calling
RMIClassLoader.loadClass with the name of the desired class as the only parameter.

The Naming Class                                                                                              [4.3]

The java.rmi.Naming class provides methods for storing and obtaining references to remote
objects in the remote object registry. The Naming class' methods take, as one of their
arguments, a name that is a URL formatted java.lang.String of the form:

        // host:port / name

where host is the host (remote or local) where the registry is located, port is the port number on
which the registry accepts calls, and where name is a simple string uninterpreted by the registry.
Both host and port are optional. If host is omitted, the host defaults to the local host. If port
is omitted, then the port defaults to 1099, the well-known port that RMI's registry, rmiregistry,
uses.

Binding a name for a remote object is associating or registering a name for a remote object
that can be used at a later time to look up that remote object. A remote object can be associated
with a name using the Naming class' bind or rebind methods. Once a remote object is registered
(bound) with the RMI registry on the local host, callers on a remote (or local) host can lookup the
remote object by name, obtain its reference, and then invoke remote methods on the object. The
lookup method returns the remote object associated with the file portion of the name. The
NotBoundException is thrown if the name has not been bound to an object. The bind method
binds the specified name to the remote object. It throws the AlreadyBoundException if the name
is already bound to an object.The rebind method always binds the name to the object even if the
name is already bound.The old binding is lost.The unbind method removes the binding between the
name and the remote object. It will throw the NotBoundException if there was no binding. The
list method returns an array of String objects containing a snapshot of the URLs bound in the
registry. Only the host and port information of the URL is needed to contact a registry for the list
of its contents; thus, the "file" part of the URL is ignored.

The UnicastRemoteObject Class                                                                     [5.3]

The class java.rmi.server.UnicastRemoteObject provides support for creating and exporting
remote objects. The class implements a remote server object with the following characteristics:

(1) References to such objects are valid only for, at most, the life of the process creating the remote object.
(2) Communication with the remote object uses a TCP transport.
(3) Invocations, parameters, and results use a stream protocol for communicating between client and server.

 Constructing a New Remote Object                                                                    [5.3.1]

A remote object implementation (one that implements one or more remote interfaces) must be
created and exported. Exporting a remote object makes that object available to accept incoming
calls from clients. For a remote object implementation, exported as a UnicastRemoteObject,
the exporting involves listening on a TCP port. (Note that more than one remote object can
accept incoming calls on the same port, so listening on a new port is not always necessary).

(1) A remote object implemention can extend the class UnicastRemoteObject to make use of it's constructors
     that export the object, or
(2) it can extend some other class (or none at all) and export the object via UnicastRemoteObject's static
      exportObject method.
 
 Notes on the UnicastRemoteObject constructors


The no argument constructor creates and exports a remote object on an anonymous (or arbitrary) 
port, chosen at runtime.The second form of the constructor takes a single argument, port, that 
specifies the port number on which the remote object accepts incoming calls. The third constructor 
creates and exports a remote object that accepts incoming calls on the specified port via a 
ServerSocket created from the RMIServerSocketFactory; clients will make connections to the 
remote object via Sockets supplied from the RMIClientSocketFactory.
.

Passing a UnicastRemoteObject in an RMI Call                                            [5.3.3]

When an object of type UnicastRemoteObject is passed as a parameter or return value in an
RMI call, the object is replaced by the remote object's stub. A remote object implementation
remains in the virtual machine  in which it was created and does not move (even by value) from
that virtual machine. In other words, a remote object is passed by reference in an RMI
call; remote object implementations cannot be passed by value.

Serializing a UnicastRemoteObject                                                                     [5.3.4]

Information contained in UnicastRemoteObject is transient and is not saved if an object of that
type is written to a user-defined ObjectOutputStream.

Remote Object Activation: Overview                                                                  [7.1]

Distributed object systems are designed to support long-lived persistent objects. Given that
these systems will be made up of many thousands (perhaps millions) of such objects, it would be
unreasonable for object implementations to become active and remain active, taking up valuable
system resources, for indefinite periods of time. In addition, clients need the ability to store persistent
references to objects so that communication among objects can be re-established after a system
crash, since typically a reference to a distributed object is valid only while the object is active.

Object activation is a mechanism for providing persistent references to objects and managing the
execution of object implementations. In RMI, activation allows objects to begin execution on
an as-needed basis. When an activatable remote object is accessed (via a method invocation)
if that remote object is not currently executing, the system initiates the object's execution inside an
appropriate Java VM.
 
Note: In the JDK, RMI provides an implementation of the activation system interfaces. In order to
use activation, you must first run the activation system daemon rmid.



Editor's note: Next in the specification are the interface definitions, followed by Section 10
Section 10 (heading listed below) has important net protocol information which you can
find, along with other omitted details, in the complete RMI specification posted on the Sun
web site.

RMI Wire Protocol                                                                                                [10]
     10.1 Overview
     10.2 RMI Transport Protocol
     10.3 RMI's Use of Object Serialization Protocol
     10.4 RMI's Use of HTTP POST Protocol
     10.5 Application Specific Values for RMI
     10.6 RMI's Multiplexing Protocol

A Exceptions In RMI
B  Properties In RMI