You are on page 1of 9

Remote Method Invocation (RMI)

Remote Method Invocation (RMI)


The Java Remote Method Invocation (RMI) system allows an object running in one Java virtual machine to
invoke methods on an object running in another Java virtual machine. RMI provides for remote
communication between programs written in the Java programming language. Such method calls appear to
the programmer the same as those operating on objects in the same program.
RMI is based on a similar, earlier technology for procedural programming called remote procedure calls
(RPCs) developed in the 1980s. RPC allows a procedural program (i.e., a program written in C or another
procedural programming language) to call a function residing on another computer as conveniently as if
that function were part of the same program running on the same computer. A goal of RPC was to allow
programmers to concentrate on the required tasks of an application by calling functions, while making the
mechanism that allows the application’s parts to communicate over a network transparent to the
programmer. RPC performs all the networking and marshalling of data (i.e., packaging of function
arguments and return values for transmission over a network). A disadvantage of RPC is that it supports a
limited set of simple data types. Therefore, RPC is not suitable for passing and returning Java objects.
Another disadvantage of RPC is that it requires the programmer to learn a special interface definition
language (IDL) to describe the functions that can be invoked remotely.
RMI is Java’s implementation of RPC for Java-object-to-Java-object distributed communication. Once a Java
object registers as being remotely accessible (i.e., it is a remote object), a client can obtain a remote
reference to that object, which allows the client to use that object remotely. The method call syntax is
identical to the syntax for calling methods of other objects in the same program. As with RPC, RMI handles
the marshalling of data across the network. However, RMI also enables Java programs to transfer complete
Java objects using Java’s object-serialization mechanism. The programmer need not be concerned with the
transmission of the data over the network. RMI does not require the programmer to learn an IDL, because
the J2SE SDK includes tools for generating all the networking code from the program’s interface definitions.
Also, because RMI supports only Java, no language-neutral IDL is required; Java’s own interfaces are
sufficient.

An Overview of RMI Applications


RMI applications often comprise two separate programs, a server and a client. A typical server program
creates some remote objects, makes references to these objects accessible, and waits for clients to invoke
methods on these objects. A typical client program obtains a remote reference to one or more remote
objects on a 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.
Chapter: Remote Method Invocation (RMI)

Distributed object applications need to do the following:


• Locate remote objects. Applications can use various mechanisms to obtain references to remote
objects. For example, an application can register its remote objects with RMI's simple naming
facility, the RMI registry. Alternatively, an application can pass and return remote object references
as part of other remote invocations.
• Communicate with remote objects. Details of communication between remote objects are
handled by RMI. To the programmer, remote communication looks similar to regular Java method
invocations.
• Load class definitions for objects that are passed around. Because RMI enables objects to be
passed back and forth, it provides mechanisms for loading an object's class definitions as well as for
transmitting an object's data.
The following illustration depicts an RMI distributed application that uses the RMI registry to obtain a
reference to a remote object. The server calls the registry to associate (or bind) a name with a remote
1
Mukul Garg
Remote Method Invocation (RMI)
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 class definitions,
from server to client and from client to server, for objects when needed.

Remote Interfaces, Objects, and Methods


Like any other Java application, a distributed application built by using Java RMI is made up of interfaces
and classes. The interfaces declare methods. The classes implement the methods declared in the interfaces
and, perhaps, declare additional methods as well. In a distributed application, some implementations
might reside in some Java virtual machines but not others. Objects with methods that can be invoked
across Java virtual machines are called remote objects.
An object becomes remote by implementing a remote interface, which has the following characteristics:
• A remote interface extends the interface java.rmi.Remote.
• Each method of the interface declares java.rmi.RemoteException in its throws clause, in
addition to any application-specific exceptions.
RMI treats a remote object differently from a non-remote object when the object is passed from one Java
virtual machine to another Java virtual machine. Rather than making a copy of the implementation object
in the receiving Java virtual machine, RMI passes a remote stub for a remote object. The stub acts as the
local representative, or proxy, for the remote object and basically is, to the client, the remote reference.
The client invokes a method on the local stub, which is responsible for carrying out the method invocation
on the remote object.
A stub for a remote object implements the same set of remote interfaces that the remote object
implements. This property enables a stub to be cast to any of the interfaces that the remote object
implements. However, only those methods defined in a remote interface are available to be called from the
receiving Java virtual machine.

Stubs and Skeletons Chapter: Remote Method Invocation (RMI)

RMI uses a standard mechanism (employed in RPC systems) 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 responsible 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, it does the following:
• initiates a connection with the remote JVM containing the remote object,
• marshals (writes and transmits) the parameters to the remote JVM,
• waits for the result of the method invocation,
• unmarshals (reads) the return value or exception returned, and
• Returns the value to the caller.
2
Mukul Garg
Remote Method Invocation (RMI)
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 JVM, each remote object may have a corresponding skeleton (in Java 2 platform-only
environments, skeletons are not required). The skeleton is responsible for dispatching the call to the actual
remote object implementation. When a skeleton receives an incoming method invocation it does the
following:
• unmarshals (reads) the parameters for the remote method,
• invokes the method on the actual remote object implementation, and
• marshals (writes and transmits) the result (return value or exception) to the caller.
Stubs and skeletons are generated by the rmic compiler.

RMI Architecture Layers


The RMI implementation is essentially built from three abstraction layers.

By using a layered architecture each of the layers could be enhanced or replaced without affecting the rest
of the system. For example, the transport layer could be replaced by a UDP/IP layer without affecting the
upper layers.

Stub and Skeleton Layer


The stub and skeleton layer of RMI lie just beneath the view of the Java developer. In this layer, RMI uses
the Proxy design pattern. In the Proxy pattern, an object in one context is represented by another (the
proxy) in a separate context. The proxy knows how to forward method calls between the participating
objects. The following class diagram illustrates the Proxy pattern.
Chapter: Remote Method Invocation (RMI)

In RMI's use of the Proxy pattern, the stub class plays the role of the proxy, and the remote service
implementation class plays the role of the RealSubject.

3
Mukul Garg
Remote Method Invocation (RMI)
A skeleton is a helper class that is generated for RMI to use. The skeleton understands how to
communicate with the stub across the RMI link. The skeleton carries on a conversation with the stub; it
reads the parameters for the method call from the link, makes the call to the remote service
implementation object, accepts the return value, and then writes the return value back to the stub.

Remote Reference Layer


The Remote Reference Layers defines and supports the invocation semantics of the RMI connection. This
layer provides a RemoteRef object that represents the link to the remote service implementation object.
The stub objects use the invoke() method in RemoteRef to forward the method call. The
RemoteRef object understands the invocation semantics for remote services.
The JDK 1.1 implementation of RMI provides only one way for clients to connect to remote service
implementations: a unicast, point-to-point connection. Before a client can use a remote service, the
remote service must be instantiated on the server and exported to the RMI system. (If it is the primary
service, it must also be named and registered in the RMI Registry).
The Java 2 SDK implementation of RMI adds a new semantic for the client-server connection. In this
version, RMI supports activatable remote objects. When a method call is made to the proxy for an
activatable object, RMI determines if the remote service implementation object is dormant. If it is dormant,
RMI will instantiate the object and restore its state from a disk file. Once an activatable object is in
memory, it behaves just like JDK 1.1 remote service implementation objects.
Other types of connection semantics are possible. For example, with multicast, a single proxy could send a
method request to multiple implementations simultaneously and accept the first reply (this improves
response time and possibly improves availability).

Transport Layer
The Transport Layer makes the connection between JVMs. All connections are stream-based network
connections that use TCP/IP.
Even if two JVMs are running on the same physical computer, they connect through their host computer's
TCP/IP network protocol stack. (This is why you must have an operational TCP/IP configuration on your
computer to run the Exercises in this course). The following diagram shows the unfettered use of TCP/IP
connections between JVMs.

Chapter: Remote Method Invocation (RMI)

On top of TCP/IP, RMI uses a wire level protocol called Java Remote Method Protocol (JRMP). JRMP is a
proprietary, stream-based protocol that is only partially specified is now in two versions. The first version
was released with the JDK 1.1 version of RMI and required the use of Skeleton classes on the server. The
second version was released with the Java 2 SDK. It has been optimized for performance and does not
require skeleton classes.

Writing an RMI Server


4
Mukul Garg
Remote Method Invocation (RMI)
The server code consists of an interface and a class. The interface defines the methods that can be invoked
from the client. Essentially, the interface defines the client's view of the remote object. The class provides
the implementation.

Defining the Remote Interface


The first step in creating a distributed application with RMI is to define the remote interface that describes
the remote methods through which the client interacts with the remote object using RMI. To create a
remote interface, define an interface that extends interface java.rmi.Remote. Interface Remote is a
tagging interface—it does not declare any methods, and therefore places no burden on the implementing
class. An object of a class that implements interface Remote directly or indirectly is a remote object and
can be accessed—with appropriate security permissions—from any Java virtual machine that has a
connection to the computer on which the remote object executes.
When computers communicate over networks, there exists the potential for communication problems. For
example, a server computer could malfunction, or a network resource could malfunction. If a
communication problem occurs during a remote method call, the remote method throws a
RemoteException, which is a checked exception.
Each method in a Remote interface must have a throws clause that indicates that the method can throw
RemoteException. RMI uses Java’s default serialization mechanism to transfer method arguments and
return values across the network. Therefore, all method arguments and return values must be
Serializable or primitive types.

Implementing the Remote Interface


The next step is to define the remote object implementation. Server class extends class
UnicastRemoteObject (package java.rmi.server) and implements Remote interface. Class
UnicastRemoteObject provides the basic functionality required for all remote objects. In particular,
its constructor exports the object to make it available to receive remote calls. Exporting the object enables
the remote object to wait for client connections on an anonymous port number (i.e., one chosen by the
computer on which the remote object executes). This enables the object to perform unicast
communication (point- to-point communication between two objects via method calls) using standard
streams based socket connections. RMI abstracts away these communication details so the programmer
can work with simple method calls. All UnicastRemoteObject constructors throw
RemoteExceptions.
Class UnicastRemoteObject provides basic functionality that remote objects require to handle
remote requests. Remote object classes need not extend this class if those remote object classes use
static method exportObject of class UnicastRemoteObject to export remote objects.
The server needs to bind the remote object to the RMI registry with the URL, using the rebind method of
Naming class. There also is a bind method for binding a remote object to the registry. Programmers use Chapter: Remote Method Invocation (RMI)
method rebind more commonly, because method rebind guarantees that if an object already has
registered under the given name, the new remote object will replace the previously registered object. This
could be important when registering a new version of an existing remote object.
A client can use the URL to obtain a remote reference to the server object. The client uses this remote
reference to invoke methods on the remote object. The URL normally is of the form
rmi://host:port/remoteObjectName
where host represents the computer that is running the registry for remote objects (this also is the
computer on which the remote object executes), port represents the port number on which the registry is
running on the host and remoteObjectName is the name the client will supply when it attempts to locate
the remote object in the registry. The rmiregistry utility program manages the registry for remote objects
and is part of the J2SE SDK. The default port number for the RMI registry is 1099.

Writing a RMI Client


5
Mukul Garg
Remote Method Invocation (RMI)
The client required the name of the computer where the server is running. The client uses the RMI URL to
access the remote object. The format URL is defined above. Client invokes Naming’s static method
lookup to obtain a remote reference to the remote object at the specified URL. Method lookup
connects to the RMI registry and returns a Remote reference to the remote object. The client can use this
remote reference as if it referred to a local object running in the same virtual machine. This remote
reference refers to a stub object on the client. Stubs allow clients to invoke remote objects’ methods.
Stub objects receive each remote method call and pass those calls to the RMI system, which performs the
networking that allows clients to interact with the remote object. The RMI layer is responsible for network
connections to the remote object, so referencing remote objects is transparent to the client. RMI handles
the underlying communication with the remote object and the transfer of arguments and return values
between the objects.

Example
In this example, you will build a simple remote calculator service and use it from a client program.
Assuming that the RMI system is already designed, you take the following steps to build a system:
1. Write and compile Java code for interfaces
2. Write and compile Java code for implementation classes
3. Generate Stub and Skeleton class files from the implementation classes
4. Write Java code for a remote service host program
5. Develop Java code for RMI client program
6. Install and run RMI system

Interfaces
The first step is to write and compile the Java code for the service interface. The Calculator interface
defines all of the remote features offered by the service:
public interface Calculator
extends java.rmi.Remote {
public long add(long a, long b)
throws java.rmi.RemoteException;

public long sub(long a, long b)


throws java.rmi.RemoteException;

public long mul(long a, long b)


throws java.rmi.RemoteException;

public long div(long a, long b) Chapter: Remote Method Invocation (RMI)


throws java.rmi.RemoteException;
}
Copy this file to your directory and compile it with the Java compiler:
>javac Calculator.java

Implementation
Next, you write the implementation for the remote service. This is the CalculatorImpl class:
public class CalculatorImpl
extends java.rmi.server.UnicastRemoteObject
implements Calculator
{

// Implementations must have an


//explicit constructor
// in order to declare the
6
Mukul Garg
Remote Method Invocation (RMI)
//RemoteException exception
public CalculatorImpl()
throws java.rmi.RemoteException {
super();
}

public long add(long a, long b)


throws java.rmi.RemoteException {
return a + b;
}

public long sub(long a, long b)


throws java.rmi.RemoteException {
return a - b;
}

public long mul(long a, long b)


throws java.rmi.RemoteException {
return a * b;
}

public long div(long a, long b)


throws java.rmi.RemoteException {
return a / b;
}
}

Again, copy this code into your directory and compile it.

Stubs and Skeletons


You next use the RMI compiler, rmic, to generate the stub and skeleton files. The compiler runs on the
remote service implementation class file.
>rmic CalculatorImpl
Try this in your directory. After you run rmic you should find the file Calculator_Stub.class and,
if you are running the Java 2 SDK, Calculator_Skel.class.

Host Server
Remote RMI services must be hosted in a server process. The class CalculatorServer is a very simple
server that provides the bare essentials for hosting.
Chapter: Remote Method Invocation (RMI)
import java.rmi.Naming;

public class CalculatorServer {

public CalculatorServer() {
try {
Calculator c = new CalculatorImpl();
Naming.rebind("rmi://localhost:1099/CalculatorService", c);
} catch (Exception e) {
System.out.println("Trouble: " + e);
}
}

public static void main(String args[]) {


new CalculatorServer();
}
}
7
Mukul Garg
Remote Method Invocation (RMI)
Client
The source code for the client follows:
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.net.MalformedURLException;
import java.rmi.NotBoundException;

public class CalculatorClient {

public static void main(String[] args) {


try {
Calculator c = (Calculator)
Naming.lookup(
"rmi://localhost
/CalculatorService");
System.out.println( c.sub(4, 3) );
System.out.println( c.add(4, 5) );
System.out.println( c.mul(3, 6) );
System.out.println( c.div(9, 3) );
}
catch (MalformedURLException murle) {
System.out.println();
System.out.println(
"MalformedURLException");
System.out.println(murle);
}
catch (RemoteException re) {
System.out.println();
System.out.println(
"RemoteException");
System.out.println(re);
}
catch (NotBoundException nbe) {
System.out.println();
System.out.println(
"NotBoundException");
System.out.println(nbe);
}
catch (
java.lang.ArithmeticException
ae) {
System.out.println(); Chapter: Remote Method Invocation (RMI)
System.out.println(
"java.lang.ArithmeticException");
System.out.println(ae);
}
}
}

Running the RMI System


You are now ready to run the system! You need to start three consoles, one for the server, one for the
client, and one for the RMI Registry.
Start with the Registry. You must be in the directory that contains the classes you have written. From there,
enter the following:
rmiregistry
8
Mukul Garg
Remote Method Invocation (RMI)
If all goes well, the registry will start running and you can switch to the next console.
In the second console start the server hosting the CalculatorService, and enter the following:
>java CalculatorServer
It will start, load the implementation into memory and wait for a client connection.
In the last console, start the client program.
>java CalculatorClient
If all goes well you will see the following output:

1
9
18
3
That's it; you have created a working RMI system. Even though you ran the three consoles on the same
computer, RMI uses your network stack and TCP/IP to communicate between the three separate JVMs.
This is a full-fledged RMI system.

Chapter: Remote Method Invocation (RMI)

9
Mukul Garg