22 RMI
Dr M. Vijayalakshmi
Java RMI
Java RMI is a mechanism to allow the invocation of methods that reside on different Java Virtual Machines (JVMs), either on a remote machine or on the same machine with different JVM (which means it resides in different address space). RMI provides Object-Oriented Remote Procedure Call (RPC). The JVMs may reside on different machines or they could be on the same machine. In either case, the method runs in a different address space than the calling process.
RMI is a core package of the JDK 1.1. It enables software developers to write distributed applications in which the methods of remote objects can be invoked from other JVMs.
Remote Method Invocation
Java’s RMI is an alternative mechanism to low level sockets. A remote method invocation is a form of Remote Procedure Call (RPC) that is available on other systems. Instead of creating objects on local machines we can create some of the objects on other machines and we can communicate with those objects as it is done normally with local objects.
How it differs from others?
Java RMI is an Object-Oriented remote procedure call mechanism.
It differs from CORBA in the following points,
- CORBA is a language and machine independent mechanism. RMI was designed for Java running on a JVM.
- CORBA includes more features like,
- Server application starting, managing persistent state and support for transactions.
- But Java RMI does not have an Object Broker.
It differs from Sun RPC and DCE RPC in the following feature,
- RMI is not language/machine independent.
- RMI supports the concept of classes with methods within a class.
- RMI also supports polymorphism.
Principal Similarities between CORBA and RMI
Both CORBA and RMI are suitable for distributed, Object-oriented, client/server systems. There is a synchronous interaction via Remote Procedure Call (RPC). RPC is implemented via client stubs and server skeletons, which hide networking and data representation. Objects can be both on client and server side.
Principal Differences between CORBA and RMI
CORBA
1. Independent of implementation language.
2. Operation invocations can be formed statically or dynamically.
3. Object implementation binding can be static or dynamic.
4. The CORBA object adapters define various object execution semantics.
5. Many integrated object services are available.
RMI
1. Requires objects to be programmed in Java.
2. Objects are platform independent.
3. Operation invocations are formed statically.
4. Mapping of names to objects is static.
5. Many object services are being defined within Enterprise JavaBeans.
6. Requires mobile code support.
The Goals of RMI
RMI supports seamless remote invocations on objects in different Java virtual machines. It also involves callbacks from servers to clients. RMI integrates the distributed object model into the Java language in a natural way while retaining most of the Java language’s object semantics.
RMI makes the differences between the distributed object model and the local Java object model apparent. It enables writing reliable distributed applications as simple as possible thereby preserving the safety provided by the Java Sun real time environment.
RMI Layers
Stub
The stub is an object, that acts as a gateway for the client side. All the outgoing requests are routed through it. It resides at the client side and represents the remote object. When the caller invokes method on the stub object, it does the following tasks:
1. It initiates a connection with remote Virtual Machine (JVM).
2. It writes and transmits (marshals) the parameters to the remote Virtual Machine (JVM).
3. It waits for the result
4. It reads (unmarshals) the return value or exception, and
5. It finally returns the value to the caller.
Skeleton
The skeleton is an object, that acts as a gateway for the server side object. All the incoming requests are routed through it. When the skeleton receives the incoming request, it does the following tasks:
1. It reads the parameter for the remote method.
2. It invokes the method on the actual remote object.
3. It writes and transmits (marshals) the result to the caller.
In the Java 2 SDK, a stub protocol was introduced that eliminates the need for skeletons.
Remote reference layer
The remote reference layer is a middle layer between the stub/skeleton layer and the transport layer. It provides the ability to support varying remote reference or invocation protocols independent of the client stub and server skeleton.
Transport layer
The Transport layer is the low-layer that ships marshal streams between different address spaces. This layer is responsible for setting up connections to remote address spaces, managing the connections, listening to incoming calls, maintaining a table of remote objects that reside in the same address space, setting up connections for an incoming call and locating the dispatcher for the target of the remote call.
Two kinds of classes
Remote class (Remote object)
A remote object is one whose instances can be used remotely. A handle to a remote object identifies where that object is located and how to contact it remotely (via RMI). When used locally, it works like any other object. When it is passed as a parameter, its handle is passed (as with ordinary Java objects).
Serializable class (Serializable object)
A serializable object is one whose value can be marshalled. It can be passed as a parameter or be a return value to a remote object which means the value of object is copied. It implements java.io.Serializable interface.
Conditions for serializability
If an object is to be serialized
1. The class must be declared as “public”.
2. The class must implement “Serializable”.
3. The class must have a no-argument constructor.
4. All fields of the class must be serializable, either primitive types or serializable objects.
Remote vs. Serializable
A Remote object lives on another computer (such as the Server)
You can send messages to a Remote object and get responses back from the object. All you need to know about the Remote object is its interface. Remote objects do not pose much of a security issue.
You can transmit a copy of a Serializable object between computers
The receiving object needs to know how the object is implemented. It needs the class as well as the interface. There is a way to transmit the class definition and accepting classes does pose a security issue.
Understanding requirements for the distributed applications
If any application performs the following tasks, it can be called as a distributed application.
1. The application need to locate the remote method
2. It need to provide the communication with the remote objects, and
3. The application need to load the class definitions for the objects.
The RMI application has all these features, so it is called the distributed application.
Steps to write the RMI program
There are 6 steps to write the RMI program.
1. Create the remote interface.
2. Provide the implementation of the remote interface.
3. Compile the implementation class and create the stub and skeleton objects using the rmic tool.
4. Start the registry service by rmiregistry tool.
5. Create and start the remote application.
6. Create and start the client application.
Example
1) Create the remote interface
For creating the remote interface, we need to extend the Remote interface and declare the RemoteException with all the methods of the remote interface.
Here, we are creating a remote interface that extends the Remote interface. There is only one method named add() and it declares RemoteException.
import java.rmi.*;
public interface Adder extends Remote
{
public int add( int x, int y ) throws RemoteException;
}
2) Provide the implementation of the remote interface
Now provide the implementation of the remote interface. For providing the implementation of the Remote interface, it is necessary to either extend the UnicastRemoteObject class, or use the exportObject() method of the UnicastRemoteObject class.
In case, we extend the UnicastRemoteObject class, we must define a constructor that declares RemoteException.
import java.rmi.*;
import java.rmi.server.*;
public class AdderRemote extends UnicastRemoteObject implements Adder
{
AdderRemote() throws RemoteException
{
super();
}
public int add(int x,int y)
{
return x+y;
}
}
3) Create the stub and skeleton objects using the rmic tool
Next step is to create the stub and skeleton objects using the rmi compiler. The rmic tool invokes the RMI compiler and creates the stub and skeleton objects.
rmic AdderRemote
4) Start the registry service by the rmiregistry tool
Now start the registry service by using the rmiregistry tool. If you don’t specify the port number, it uses a default port number.In this example, we are using the port number 5000.
rmiregistry 5000
5) Create and run the server application
Now rmi services needs to be hosted in a server process. The Naming class provides methods to get and store the remote object.
In this example, we are binding the remote object by the name Add.
import java.rmi.*;
import java.rmi.registry.*;
public class MyServer
{
public static void main(String args[])
{
try
{
Adder stub=new AdderRemote();
Naming.rebind(“rmi://localhost:5000/Add”, stub);
}catch(Exception e)
{
System.out.println(e);
}
}
}
6) Create and run the client application
At the client we are getting the stub object by the lookup() method of the Naming class and invoking the method on this object.
In this example, we are running the server and client applications, in the same machine so we are using localhost.
import java.rmi.*;
public class MyClient{
public static void main(String args[]){
try{
Adder stub=(Adder)Naming.lookup(“rmi://localhost:5000/Add”);
System.out.println(stub.add(34,4));
}catch(Exception e){}
}
}
Output
Figure 24.1 shows the screen shot of invoking the RMI compiler and starting the RMI registry at port no 5000.
Figure 24.1 Invoking RMI Registry
24.1 Invoking RMI Registry
Figure 24.2 shows the screen shot of running the server application.
Figure 24.2 Running Server Application
Figure 24.3 shows the screen shot of executing the client application.
Figure 24.3 Executing Client Application
Distributed Garbage Collection
When stand-alone applications are developed using Java, objects that are no longer referenced by any client are automatically deleted. This is a desirable feature when developing distributed applications. The RMI system provides a distributed garbage collector that automatically deletes remote objects that are no longer referenced by any client.
Security
- There is no authentication; a client just requests through the object (stub), and the server supplies it. Subsequent communication is assumed to be from the same client.
- There is no access control to the objects.
- There are no security checks on the RMI registry itself, any caller is allowed to make request.
- There is no version control between the stubs and the skeletons, making it possible for client to use a down-level stub to access a more recent skeleton breaking release-to-release binary compatibility.
Summary
This module explains about RMI, allowing one Java Virtual Machine to invoke methods of another, and to share any Java object type, even if client or server has never come across that object type before. It gave a broad view of how RMI differs from other APIs and it explored the RMI layers. It also discussed about the steps to write an RMI program with an example.
References