Remote Method Invoacation - RMI PDF
Remote Method Invoacation - RMI PDF
Remote Method Invoacation - RMI PDF
Java-RMI
Introduction
The Java RMI is Java’s native scheme for creating and using remote objects. Java RMI
provides the following elements:
4. A network protocol for communication between remote objects and their client
(this protocol is JRMP, i.e. Java Remote Method Protocol).
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.
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.
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
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
Stub Skeleton
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.
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 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
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;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.RemoteException;
5
15CS51C – Java Programming Odd Semester 2017 - 2018
//non-remote method
private String doSomething(String what, String todo) {
String result = what + todo + “.”;
}
}
6
15CS51C – Java Programming Odd Semester 2017 - 2018
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.
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:
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
/*interface:calc.java*/
import java.rmi.Remote;
import java.rmi.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;
}
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)
{}
}
}
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
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;
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.
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:
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.
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
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.
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
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.
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