2 Distributed Object Model


2.1 Distributed Object Applications

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 application 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 application is sometimes referred to as a distributed object application.

Distributed object applications need to:

The illustration below depicts an RMI distributed application that uses the registry to obtain references to a remote object. The server calls the registry to associate a name with a remote object. The client looks up the remote object by its name in the server's registry and then invokes a method on it. The illustration also shows that the RMI system uses an existing web server to load bytecodes of classes written in the Java programming language, from server to client and from client to server, for objects when needed. RMI can load class bytecodes using any URL protocol (e.g., HTTP, FTP, file, etc.) that is supported by the Java platform.

This illustration depicts an RMI distributed application that uses the registry to obtain references to a remote object.
This illustration depicts an RMI distributed application that uses the registry to obtain references to a remote object.

2.2 Definition of Terms

In the Java SE platform's 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 interfaces written in the Java programming language that declare the methods of the remote object.

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.

2.3 The Distributed and Nondistributed Models Contrasted

The Java SE platform's distributed object model is similar to the Java SE platform's object model in the following ways:

The Java SE platform's distributed object model differs from the Java SE platform's object model in these ways:

2.4 Overview of RMI Interfaces and Classes

The interfaces and classes that are responsible for specifying the remote behavior of the RMI system are defined in the java.rmi package hierarchy. The following figure shows the relationship between several of these interfaces and classes:

Relationship between several of these interfaces and classes
Relationship between several of these interfaces and classes

2.4.1 The java.rmi.Remote Interface

In RMI, a remote interface is an interface that declares a set of methods that may be invoked from a remote Java virtual machine. A remote interface must satisfy the following requirements:

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

public interface Remote {}

A remote interface must at least extend the interface java.rmi.Remote (or another remote interface that extends java.rmi.Remote). However, a remote interface may extend a non-remote interface under the following condition:

For example, the following interface BankAccount defines a remote interface for accessing a bank account. It contains remote methods to deposit to the account, to get the account balance, and to withdraw from the account:

public interface BankAccount extends java.rmi.Remote {
        public void deposit(float amount)
                throws java.rmi.RemoteException;
        public void withdraw(float amount)
                throws OverdrawnException, java.rmi.RemoteException;
        public float getBalance()
                throws java.rmi.RemoteException;
}

The next example shows a valid remote interface Beta that extends a non-remote interface Alpha, which has remote methods, and the interface java.rmi.Remote:

public interface Alpha {
        public final String okay = "constants are okay too";
        public Object foo(Object obj)
                throws java.rmi.RemoteException;
        public void bar() throws java.io.IOException;
        public int baz() throws java.lang.Exception;
}

public interface Beta extends Alpha, java.rmi.Remote {
        public void ping() throws java.rmi.RemoteException;
}

2.4.2 The RemoteException Class

The java.rmi.RemoteException class is the superclass of exceptions thrown by the RMI runtime during a remote method invocation. To ensure the robustness of applications using the RMI system, each remote method declared in a remote interface must specify java.rmi.RemoteException (or one of its superclasses such as java.io.IOException or java.lang.Exception) in its throws clause.

The exception java.rmi.RemoteException is thrown when a remote method invocation fails for some reason. Some reasons for remote method invocation failure include:

The class RemoteException is a checked exception (one that must be handled by the caller of a remote method and is checked by the compiler), not a RuntimeException.

2.4.3 The RemoteObject Class and its Subclasses

RMI server functions are provided by java.rmi.server.RemoteObject and its subclasses, java.rmi.server.RemoteServer and java.rmi.server.UnicastRemoteObject and java.rmi.activation.Activatable.

2.5 Implementing a Remote Interface

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

For example, the following class BankAcctImpl implements the BankAccount remote interface and extends the java.rmi.server.UnicastRemoteObject class:

package mypackage;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class BankAccountImpl
        extends UnicastRemoteObject
        implements BankAccount
{
        private float balance = 0.0;

        public BankAccountImpl(float initialBalance)
                throws RemoteException
        {
                balance = initialBalance;
        }
        public void deposit(float amount) throws RemoteException {
                ...
        }
        public void withdraw(float amount) throws OverdrawnException,
                RemoteException {
                ...
        }
        public float getBalance() throws RemoteException {
                ...
        }
}

Note:

2.6 Parameter Passing in Remote Method Invocation

An argument to, or a return value from, a remote object can be any object that is serializable. This includes primitive types, remote objects, and non-remote objects that implement the java.io.Serializable interface. For more details on how to make classes serializable, see the "Java Object Serialization Specification." Classes, for parameters or return values, that are not available locally are downloaded dynamically by the RMI system. See the section on "Dynamic Class Loading" for more information on how RMI downloads parameter and return value classes when reading parameters, return values and exceptions.

2.6.1 Passing Non-remote Objects

A non-remote object, that is passed as a parameter of a remote method invocation or returned as a result of a remote method invocation, is passed by copy; that is, the object is serialized using the object serialization mechanism of the Java SE platform.

So, when a non-remote object is passed as an argument or return value in a remote method invocation, the content of the non-remote object is copied before invoking the call on the remote object.

When a non-remote object is returned from a remote method invocation, a new object is created in the calling virtual machine.

2.6.2 Passing Remote Objects

When passing an exported remote object as a parameter or return value in a remote method call, the stub for that remote object is passed instead. Remote objects that are not exported will not be replaced with a stub instance. A remote object passed as a parameter can only implement remote interfaces.

2.6.3 Referential Integrity

If two references to an object are passed from one JVM to another JVM in parameters (or in the return value) in a single remote method call and those references refer to the same object in the sending JVM, those references will refer to a single copy of the object in the receiving JVM. More generally stated: within a single remote method call, the RMI system maintains referential integrity among the objects passed as parameters or as a return value in the call.

2.6.4 Class Annotation

When an object is sent from one JVM 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.

2.6.5 Parameter Transmission

Parameters in an RMI call are written to a stream that is a subclass of the class java.io.ObjectOutputStream in order to serialize the parameters to the destination of the remote call. The ObjectOutputStream subclass overrides the replaceObject method to replace each exported remote object with its corresponding stub instance. Parameters that are objects are written to the stream using the ObjectOutputStream's writeObject method. The ObjectOutputStream 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:

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. See the section "Dynamic Class Loading" for more information on how annotateClass is used.

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.

Any other default behavior of ObjectOutputStream for writing objects (and similarly ObjectInputStream for reading objects) is maintained in parameter passing. For example, the calling of writeReplace when writing objects and readResolve when reading objects is honored by RMI's parameter marshal and unmarshal streams.

In a similar manner to parameter passing in RMI as described above, a return value (or exception) is written to a subclass of ObjectOutputStream and has the same replacement behavior as parameter transmission.

2.7 Locating Remote Objects

A simple bootstrap name server is provided for storing named references to remote objects. A remote object reference can be stored using the URL-based methods of the class java.rmi.Naming.

For a client to invoke a method on a remote object, that client must first obtain a reference to the object. A reference to a remote object is usually obtained as a parameter or return value in a method call. The RMI system provides a simple bootstrap name server from which to obtain remote objects on given hosts. The java.rmi.Naming class provides Uniform Resource Locator (URL) based methods to look up, bind, rebind, unbind, and list the name-object pairings maintained on a particular host and port.