Remote Method Invoacation - RMI PDF

Download as pdf or txt
Download as pdf or txt
You are on page 1of 15

15CS51C – Java Programming Odd Semester 2017 - 2018

Java-RMI
Introduction
The Java RMI is Java’s native scheme for creating and using remote objects. Java RMI
provides the following elements:

1. Remote object implementations.

2. Client interfaces, or stubs, to remote objects.

3. A remote object registry for finding objects on the network.

4. A network protocol for communication between remote objects and their client
(this protocol is JRMP, i.e. Java Remote Method Protocol).

5. A facility for automatically creating (activating) remote objects on-demand.

Each of these elements (except the last one) has a Java interface defined for it in the java.rmi
package and its subclasses. RMI is part of the core Java API and has been enhanced for JDK 1.2
(Java 2 platform) in recognition of the critical need for support for distributed objects in
distributed-application development.

 With RMI, you can get a reference to an object that “lives” in a remote process on
remote hosts and invoke methods on it as if it were a local object running within the
same Java virtual machine as your code.

 Each remote object implements a remote interface that specifies which of its methods can
be invoked by clients.

Prior to RMI, a distributed application involved socket programming, where a raw


communication channel was used to pass messages and data between two remote processes.
The programmer needed to define a low-level message protocol and data transmission format
between processes in the distributed application.

 With RMI, you can “export” an object as a remote object, so that other remote
processes/agents can access it directly as a Java object. RMI handles all the underlying
networking needed to make your remote method calls work.

 RMI is a Java-only distributed object scheme; the distributed objects in an RMI-based


distributed application have to be implemented in Java. This could be a problem when
interfacing with legacy applications.

 CORBA, on the other hand, is a language-independent distributed object scheme. It is


however, more complex to work with than RMI.

Advantages of RMI
 Since RMI is a Java native, integration of its remote object facilities into a Java application is
seamless.
 You can use RMI-enabled objects as if they live in the local Java environment.
 RMI extends the internal garbage-collection mechanisms of the standard JVM to provide
distributed garbage collection of remotely exported objects.
 RMI is platform-independent (though not language-independent).

1
15CS51C – Java Programming Odd Semester 2017 - 2018

 RMI is easy to learn.

 You can migrate entire objects (i.e. class byte codes are portable) to a remote host via object
serialization in RMI. This is not possible in CORBA.

Your options, if you have a distributed application with heterogeneous components, some of
which are written in Java and some that are not:

 You can use CORBA since it is supports language-independent object interfaces (the
Java IDL API included in the Java 2 platform covers the Java interface to CORBA).

 You can use RMI, wrapping the non-Java code with RMI-enabled Java objects using the
Java Native Interface (JNI).

 The third option involves the new RMI/IIOP functionality that allows RMI objects to
communicate directly with remote CORBA objects over IIOP (Internet Inter-Orb
Protocol).

RMI Architecture

Client objects Logical Path Server Objects

Stub Skeleton

Remote reference layer Remote reference layer

RMI Transport layer Physical path RMI Transport layer

The RMI runtime architecture

There are three layers that comprise the basic remote-object communication facilities in RMI:
1. The stub/skeleton layer, which provides the interface that client and server application
objects use to interact with each other.
2. The remote reference layer, which is the middleware between the stub/skeleton layer and
the underlying transport protocol.
3. The transport protocol layer, which is the binary data protocol that sends remote object
requests over the wire.

In the figure, the server is the application that provides remotely accessible objects, while the
client is any remote application that communicates with these server objects.

Description of the architecture:


1. The client uses the client-side stub to make a request of the remote object. The server
object receives this request from a server-side object skeleton.
2. A client initiates an RMI invocation by calling a method on a stub object. The stub
maintains an internal reference to the remote object it represents and forwards the

2
15CS51C – Java Programming Odd Semester 2017 - 2018

method invocation request through the remote reference layer by marshaling the
method arguments into serialized form and asking the remote reference layer to
forward the method request and arguments to the appropriate remote object.
3. Marshaling involves converting local objects into portable form so that they can be
transmitted to a remote process. Each object (e.g. a String object, an array object, or a
user defined object) is checked as it is marshaled, to determine whether it implements
the java.rmi.Remote interface. If it does, its remote reference is used as its marshaled
data. If it isn’t a Remote object but is rather a Serializable object, the object is
serialized into bytes that are sent to the remote host and reconstructed into a copy of
the local object. If the object is neither Remote nor Serializable, the stub throws a
java.rmi.MarshalException back to the client.
4. If the marshaling of method arguments succeeds, the client-side remote reference
layer receives the remote reference and marshaled arguments from the stub.
5. The remote reference layer converts the client request into low-level RMI transport
requests, i.e., into a single network-level request and sends it over the wire to the sole
remote object (since in Java 2 the communication style supported is the point-to-
point object references) that corresponds to the remote reference passed along with
the request.
6. On the server, the server-side remote reference layer receives the transport-level
request and converts it into a request for the server skeleton that matches the
referenced object.
7. The skeleton converts the remote request into the appropriate method call on the
actual server object. This involves unmarshaling the method arguments into the
server environment and passing them to the server object. Arguments sent as remote
references are converted into local stubs on the server, and arguments sent as
serialized objects are converted into local copies of the originals.
8. If the method calls generates a return value or an exception, the skeleton marshals the
object for transport back to the client and forwards it through the server reference
layer.
9. The result is sent back using the appropriate transport protocol (e.g. Socket API using
TCP/IP), where it passes through the client reference layer and stub, is unmarshaled
by the stub, and is finally handed back to the client thread that invoked the remote
method.

RMI Object Services

RMI provides some basic object services on top of its remote object architecture that can be
used by the distributed application designer. These services are:
1. Naming/Registry Service
 A server process needs to register one (or more) RMI-enabled objects with its
local RMI registry (represented by the Registry interface) using a name that
clients can use to reference it.
 A client can obtain a stub reference to the remote object by asking for the object
by name through the Naming interface. The Naming.lookup() method takes the
name of a remote object and locates the object on the network. The object’s name
is in a URL-like syntax that includes the name of the object’s host and the
object’s registered name.
 Once the lookup() method locates the object’s host, it consults the RMI registry
on the host and asks for the object by name. If the registry finds the object, it
generates a remote reference to the object and delivers it to the client process,
where it is converted into a stub (local) reference that is returned to the caller.

3
15CS51C – Java Programming Odd Semester 2017 - 2018

2. Distributed Garbage Collection


 This is an automatic process that the application developer does not have to worry
about.
Description:
Every server that contains RMI-exported objects automatically maintains a list of
remote references to the objects it serves. Each client that requests and receives a
reference to a remote object is issued this remote reference through the remote reference
layer of the object’s host process. The reference layer automatically keeps a record of this
reference in the form of an expirable lease on the object.
When the client is done with the reference it allows the remote stub to go out of
scope and notifies the server that it is done with the reference to the object. Then the
reference layer on the server automatically deletes the record of the remote reference and
informs the client’s reference layer that this remote reference has expired. Should the
lease on the object expire then the reference layer on the server also deletes the record of
the remote reference. This is used to deal with situations when a client or network failure
prevents a client from notifying the server that it is done with its reference to an object.
When an object has no further remote references recorded in the remote reference
layer, it becomes a candidate for garbage collection. If there are also no local references
to the object then this object is picked up the garbage collector in the next run of the
system garbage collector.

3. Object Activation Service


 This service is new to RMI as of version 1.2 of the Java 2 platform. It provides a way
for a server object to be activated automatically when a client requests it.
Without remote activation, a server object has to be registered with the RMI registry
service from within a running JVM. If the server VM crashes, the server object becomes
unavailable and any existing client references to the object are lost.
With remote activation, a server object can be created within a new or existing VM and a
reference to this newly created object can be obtained for the client that caused the
activation. A server object that wants to be activated automatically needs to register an
activation method with the RMI activation daemon (rmid) running on its host.

Defining Remote Objects

 Defining a remote RMI object involves specifying a remote interface for the object,
then providing a class that implements this interface.
 The remote interface and implementation class are then used by RMI to generate a
client stub and server skeleton for your remote object. The communication between
local objects and remote objects is handled using these stubs and skeletons.
 The RMI compiler (rmic) automatically generates the stub and skeleton classes based
on the remote interface and implementation classes provided by you.
e.g. rmic YourServerImpl
The stub and skeleton classes act as go-betweens for the client application and the actual
server object. For the client stub class, the rmic compiler generates an implementation of each
remote method that packages (marshals) the method arguments and transmits them to the server.
For the server skeleton class, the RMI compiler generates another set of implementations of the
remote methods, but these are designed to receive the method arguments from the remote method
call, unpackage them, and make the corresponding call on the object implementation.

4
15CS51C – Java Programming Odd Semester 2017 - 2018

Whatever the method call generates (return data or an exception), the results are packaged and
transmitted back to the remote client. The client stub method (which is still executing
(synchronous call) at this point) unpackages the results and delivers them to the client as the
result of its remote method call.

 Every object you want to distribute using RMI has to extend the java.rmi.Remote
interface.
 Every method in the remote interface has to declare that it throws a
java.rmi.RemoteException or one of the parent classes of RemoteException.

The first requirement allows RMI to tag remote objects as such and to differentiate between
objects that are remote and those that are not.
The second requirement is needed to deal with errors that can happen during a remote
session. Such errors include: client-side error (an argument can’t be marshaled), errors during
transport of data between client and server (network connection is lost), errors on the server side
(the method throws a local exception that needs to be sent back to the remote caller).
The RemoteException class is used by RMI as a base exception class for any of the different
types of problems that might occur during a remote method call. Any method declared in a
Remote interface is assumed to remotely callable, so every method has to declare that it might
throw a RemoteException.
Note: the implementation class of your Remote interface can include other methods that are not
remotely callable. These methods do not have to be declared as throwing a RemoteException.

Example

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface YourServer extends Remote {


public String doThis(String todo) throws RemoteException;
public String doThat(String todo) throws RemoteException;
}

RMI Classes for Remote Object Implementations

Example of an implementation of a Remote class:

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

public class YourServerImpl extends UnicastRemoteObject implements YourServer


{
//constructor
public YourServer Impl() throws RemoteException { }

//remotely accessible methods


public String doThis(String todo) throws RemoteException {
return doSomething(“this”, todo);
}

public String doThat(String todo) throws RemoteException {

5
15CS51C – Java Programming Odd Semester 2017 - 2018

return doSomething(“that”, todo);


}

//non-remote method
private String doSomething(String what, String todo) {
String result = what + todo + “.”;
}
}

 The YourServerImpl class extends the UnicastRemoteObject class. This is a class in


the java.rmi.server package that extends the java.rmi.server.RemoteServer, which
itself extends java.rmi.server.RemoteObject, the base class for all RMI objects.
RemoteObject
RemoteObject is an abstract class that implements the equals(), toString(), etc., methods
inherited from Object in a way that makes sense for remote objects. The equals() method, for
example, is implemented to return true if the internal remote references of the two RemoteObject
objects are equal (i.e. they both point to the same server object).
RemoteServer
RemoteServer is an abstract class that extends RemoteObject. It acts as a base class for
classes that define various semantics for remote objects, e.g. point-to-point reference scheme, or a
scheme where there are multiple copies of an object scattered across a network etc. At present,
only point-to-point, non-persistent remote references are supported by the UnicastRemoteObject
class, which is a subclass of RemoteServer.
UnicastRemoteObject
This is a concrete subclass of RemoteServer that implements point-to-point remote
references over TCP/IP networks. These references are nonpersistent: remote references to a
server object are only valid during the lifetime of the server object. If the VM containing the
object exits, any existing remote references on clients become invalid and generate
RemoteException objects if used.
Activatable
This concrete subclass of RemoteServer is part of the new RMI object activation facility
in Java 1.2 and can be found in the java.rmi.activation package. If a remote method request is
received on the server host for an Activatable object, and the target object is not executing at that
time, the object can be started automatically by the RMI activation daemon.

Creating Stubs and Skeletons


The RMI compiler (rmic) generates the stub and skeleton.
The command is:
rmic YourServerImpl
The command
rmic –d /usr/local/classes YourServerImpl
generates stub and skeleton classes in the specified directory.

Registry and Naming Services


 The principal use for the Registry and Naming classes in an RMI application is as a means to
bootstrap your distributed applications. A server process exports its objects through its local
RMI registry daemon. Clients look up these objects through the Naming facility to get remote
references to them.
 Java 2 provides an RMI registry daemon, rmiregistry. This utility creates a Registry object
that listens to a specified port and then goes into a wait loop, waiting for local processes to
register objects with it or for clients to connect and lookup RMI objects in its registry.

6
15CS51C – Java Programming Odd Semester 2017 - 2018

The command is:


rmiregistry 5000 &
Without the port argument, the RMI registry listens on port 1099.
 The rebind() method of the java.rmi.Naming interface is used to register an object with a
name in the local registry, where the name for an object can be any unique string. You can
remove the object binding using the unbind() method. Note: the rebind(), and unbind()
methods can only be called by clients running on the same host as the registry, else a
java.rmi.AccessException is received by the client.
 You can lookup a particular object in the registry using the lookup() method, while list()
returns the names of all the objects registered with the local registry. Only Remote objects
can be bound to a name in the Registry since only they are capable of supporting remote
references.
Example of registering an object:
import java.rmi.Naming;

try {
YourServerImpl serv = new YourServerImpl();
Naming.rebind("Johnserver", serv);
}
catch(Exception e) {
e.printStackTrace();
}

The Naming class lets a client look up local and remote objects using an URL-like
naming syntax. The format of this URL is:
rmi://objhost.org:1099/objName
where objhost.org is the host of the object, 1099 is the registry port, and objName is the registered
name of the object.

Example of looking up an object,

import java.rmi.Naming;
try
{
YourServer rmtserver = (YourServer)Naming.lookup(“rmi://osprey.unf.edu/Johnserver”);
}
catch(Exception e) {
e.printStackTrace();
}

If you have a client running on the same host as YourServerImpl object, the lookup command is:
YourServer rmtServer = (YourServer)Naming.lookup(“Johnserver”);
Alternatively, you can use the LocateRegistry and Registry interfaces to look up the same object
as in:

Registry rmtRegistry = LocateRegistry.getRegistry(“osprey.unf.edu”);


YourServer rmtServer = (YourServer) rmtRegistry.lookup(“Johnserver”);

Note: The Naming.lookup() method internally makes the same two calls listed above.

7
15CS51C – Java Programming Odd Semester 2017 - 2018

Mechanisms used to pass arguments and return results from remote methods:
This depends on the type of data being passed.
 Primitive types (int, boolean, double etc.) are passed by value, just as in a local Java
method invocation.

 If the object is a Remote object, a remote reference for the object is generated, and the
reference is marshaled and sent to the remote process.
The remote reference is received on the other end and converted into a stub for the original
object. This process applies to both the method arguments and return values.

 If the object is Serializable but not Remote, the object is serialized and streamed to the
remote process in byte form. The receiver converts the bytes into a copy of the original
object.

 If the method argument or return value is not serializable (i.e., it’s not a primitive data
type or an object that implements Serializable), the object can’t be sent to the remote
client, and a java.rmi.MarshalException is thrown.

Factory Classes
 When a reference to a remote object is obtained through the RMI registry and then used
to request additional remote references, the registered remote object is referred to as a
factory class.
 Using remote references obtained through method calls on factory objects, client
applications can dynamically request the creation of new remote objects, without the
objects being registered individually with the server registry.

8
15CS51C – Java Programming Odd Semester 2017 - 2018

Complete Program Example1:

/*interface:calc.java*/

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface calc extends Remote


{
int add(int a,int b)throws RemoteException;
int sub(int a,int b)throws RemoteException;
int mul(int a,int b)throws RemoteException;
int div(int a,int b)throws RemoteException;
}

/*Server Program:calserver.java*/

import java.io.*;
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
public class calserver extends UnicastRemoteObject implements inte
{
public calserver()throws RemoteException
{
super();
}
public int add(int a,int b)throws RemoteException
{
return a+b;
}
public int sub(int a,int b)throws RemoteException
{
return a-b;
}
public int mul(int a,int b)throws RemoteException
{
return a*b;
}
public int div(int a,int b)throws RemoteException
{
return a/b;
}

public static void main(String args[])


{
try
{
calc c1=new calserver();
Naming.rebind(“mycalc”,c1);
System.out.println("Server bound and started");

9
15CS51C – Java Programming Odd Semester 2017 - 2018

}
catch(Exception e)
{
e.printStackTrace();
}
}
}

/*Client Program:cclient.java*/

import java.rmi.*;
public class calclient
{
public static void main(String args[])
{
try
{
calc c=(inte)Naming.lookup(“mycalc”);
System.out.println("Ready to continue");
int i=c.add(2,3);
int j=c.sub(3,2);
int k=c.mul(2,4);
int l=c.div(4,2);
System.out.println(i);
System.out.println(j);
System.out.println(k);
System.out.println(l);
}
catch(Exception e)
{}
}
}

Procedure to compile and run:

D:\java\bin>javac calc.java

D:\java\bin>javac calserver.java

D:\java\bin>javac calclient.java

D:\java\bin>rmic calserver

D:\java\bin>start rmiregistry

D:\java\bin>java calserver

Server bound and started.

/*In new DOS window:*/

10
15CS51C – Java Programming Odd Semester 2017 - 2018

D:\java\bin\java calclient

Ready to continue
5
1
8
2

11
15CS51C – Java Programming Odd Semester 2017 - 2018

Example 2
Say we’re building a remote banking system using the Account object. The server
provides services to remote clients running on PCs, embedded in ATMs etc. On the server, we
could run an RMI registry, create an Account object for every account we have on record, and
register each one with the RMI registry using the account name.
Registry local = LocateRegistry.getRegistry();
local.bind(“Abrams, John”, new AccountImpl(“John Abrams”));
local.bind(“Adams, John”, new AccountImpl(“John Adams”));
:
:
This is unwieldy. Starting the server can take long, as thousands of accounts need to be
registered, many of them unnecessarily, since many accounts may not see any activity before the
next down time. Also, accounts that are created or closed during the server’s lifetime need to be
added or removed from the RMI registry, as well as from the bank’s database of accounts. So we
define a factory class for Account objects, as in:
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface AccountManager extends Remote {


public Account getAccount(String name) throws RemoteException;
public Boolean newAccount(Account s) throws RemoteException;
}

The AccountManager lets a client ask for an account by name, using the getAccount()
remote method. The method returns a reference to an Account object that corresponds to the
account. Once the client has an Account reference, transactions against the account can be done
through method calls on the Account object. The AccountManager also has a newAccount()
method that allows clients to add new accounts to the underlying database.

The server implementation of the getAccount() method simply needs to look up the
named account in the database, create an AccountImpl object to represent the account, and return
the object to the client as a remote reference. Since Account objects are Remote objects, the RMI
remote reference layer automatically creates a remote reference for the Account object, and the
client that called the getAccount() method receives a stub for the Account object (thus the
Account object is created on the server but is not registered with the registry and nor does the
client need to call Naming.lookup() to look this object up.
This avoids keeping the RMI registry in sync with the database and an unnecessary
shadow of the database. Only the AccountManager object is registered with the registry and the
client would only need to call Naming.lookup() to get a remote reference to the AccountManager
object.) The AccountManager object can access the bank’s database directly to find accounts and
create corresponding Account remote objects.

Dynamically Loaded Classes


 The RMI runtime system provides its own dynamic class loader, the RMIClassLoader, to
load stubs and skeletons for remote interfaces, as well as the classes for objects used as
arguments of remote methods or return values.

A client needs the interface class for the remote object and its stub class. On the server side,
the skeleton class for the remote object and the implementation class, need to be loaded in order
to run the server object that is being remotely exported.

12
15CS51C – Java Programming Odd Semester 2017 - 2018

First the default local class loader tries to find the referenced class locally (e.g. the stub class)
in the local CLASSPATH. If it can’t find it locally, then the RMIClassLoader tries to load the
class bytes remotely.

When the RMI runtime system marshals a remote object stub, method argument, or return
value, it encodes a URL in the marshaled bytestream to tell the process on the receiving end of
the stream where to look for the class file for the marshaled object.

 The value of the java.rmi.server.codebase property for the JVM marshaling the object is
sent in the marshaled byte stream. To set the property:

java –Djava.rmi.server.codebase=http://objhost.org/classes/ RMIProcess

Any remote process that needs to load classes for objects received from this process during an
RMI session uses this HTTP URL in order to find them if the classes can’t be found on the local
CLASSPATH.

This applies either if RMIProcess is serving remote objects itself through an RMI registry if
RMIProcess is passing objects into methods it is calling on other remote objects.

 The RMIClassLoader takes the URL in the marshaled bytestream and opens a URL
connection to the specified host to load the needed classes.

 If both the local class search and this remote URL search fail to find the required classes,
the unmarshal operation generates an exception, and the remote method call fails.

 In order for a Java runtime system to even attempt to load classes remotely, it has to have
a security manager installed that allows remote class loading. The
java.rmi.RMISecurityManager
is used for this.

 In both your RMI object server and clients, include the following line before any RMI
calls:
System.setSecurityManager(new RMISecurityManager());

 The default Java security policy does not allow all the networking operations required to
resolve a class from a remote host. You will need to use a policy file that opens up
network permissions to allow this.

A sample policy file (called mypolicy.txt) might contain the following:

permission java.net.SocketPermission “objhost.org”, “accept,connect”


This gives the RMI object server objhost.org the permission to open connections to the local
machine.

Next, specify the policy file on the command line when you start your RMI process as in:
java –Djava.security.policy=mypolicy.txt RMIProcess

13
15CS51C – Java Programming Odd Semester 2017 - 2018

Interfacing with legacy applications


1. RMI and Native Method calls
By using Java’s Native Interface API, it is possible to wrap existing C or C++ code with
a Java interface and then export this interface remotely through RMI.

Advantage: You’re running Java at both ends of the remote communication and avoiding use of
CORBA, which may be overkill for your application. Using the simpler RMI may be an
advantage.

2. CORBA
A CORBA object implemented in the same language as the native code (C/C++) is
created and exported on the server. Remote Java clients can get a Java stub to this
CORBA object using JavaIDL.

Advantage: you don’t need Java on the server. Since this is presumably a mainframe, finding a
stable JVM and development kit for the platform may be a problem. If a Java implementation
isn’t available or if installing additional software on the legacy server isn’t desirable, CORBA is
your only option.

3. RMI over IIOP


 RMI objects can communicate directly with CORBA objects using IIOP, the CORBA
network interface protocol.

 This means that an RMI object using RMI/IIOP can communicate with a remote CORBA
object, regardless of the implementation language of the CORBA object and the CORBA
object can interact with your Java RMI objects directly.

Object Serialization

 To copy an object, you need to convert it into a stream of bytes.

 Object serialization is a scheme that converts objects into a byte stream that is passed to other
machines; these rebuild the original object from the bytes.

 An object you want to serialize must implement the java.io.Serializable interface.

 In RMI, serialization is used to marshal/unmarshal method arguments that are objects, but
that are not remote objects.

 Any object argument to a method on a remote object in RMI must implement the Serializable
interface.

14
15CS51C – Java Programming Odd Semester 2017 - 2018

15

You might also like