Remote Method Invocation

 

 

1.RMI

2.WHY RMI         

3.Stubs and   Skeletons

4.UnicastRemoteObject  

 

5.Remote interface  

6.Naming  

 

7.The Registry

 

8.Class Hierarchy  

 

9.Passing Remote  Reference 

10.Finding Remote  Objects

11.Dynamic Class Loading

12.Running the Client and Server from different JVMs

         The required steps to dynamically download classes under various situations

           

:                   

 

Remote method invocation allows objects residing in one JVM execute methods of objects residing in another JVM. The two JVMs can be in the same machine or executing on different machines located in a network. The object executing a remote method does so as if the remote object was present locally (i.e. accessible through the local classpath.

 

Why RMI?

 

Why do we need Remote Method Invocation? To understand this a review of the traditional approach to invoking remote methods is warranted. Traditional method of doing this was by use of Stream Sockets. Stream sockets can be used to pass primitive data types or objects(provided they implement the Serializable interface) between two hosts on a network. Stream sockets always passed data by value. That is copies of objects were passed back and forth to effect communication..Consider the example of an Account object whose class definition may be as given below.

 

public class Account implements Serializable

{

    protected String account_name;

    protected String account_type;

    protected double balance;

 

public Account(String name, String type,double balance)

{

account_name=name;

account_type=type;

this.balance=balance;

 

public void deposit(double amount)

            {

  balance+=amount;

}

 

public synchronized  double withdraw(double amount)

{

             if(balance>amount)

               {

             balance -= amount;

              return amount;

                }

             else

   return 0;

           

          }

}

 

Now imagine a client server scenario, in which a client wants to update an Account object present on the server.The client will typically open a connection to the server and request the object by name.The server will then send a copy of this object to the client through an ObjectOutputStream.The client will receive this object, update the object and  send the modified object to the server.The server in turn will replace the server object with the new object received from the client.

 

If many clients are requesting updates on objects residing on the server, the number of object copies that travel on the network increases proportionally. The point is that since Objects are passed by value, a copy of the object is sent to the requesting client Thus any modification made on the passed object is not reflected on the server unless the modified object is passed back. This increases network traffic and can have serious implications on the network band-width. For more complex operations like querying a database located on the server the performance implications will be extremely high.

 

Another problem with this approach is that if the address of the server changes, the client needs to know the location of the new server before it can access the object. That is, the objects are not inherently location transparent.

 

If it were possible for a client to invoke the methods of objects residing on the server with out actually downloading the object, considerable performance improvements can be achieved. Further it were possible for a client to access a remote object regardless of on which server the object actually existed, the objects become location transparent. RMI ( and before RMI , RPC or Remote Procedure Calls) achieves precisely this objective. Remote Method Invocation involves using the various classes and interfaces available in the java.rmi and java.rmi.server packages. These classes and interfaces provide a framework for an application to access objects residing on remote hosts by reference(not value).Once a client obtains a reference to a remote object, it can invoke the methods on these remote objects as if they existed locally. Any modification made to the object through the remote object reference is reflected on the server. Thus copies are never passed over the network.

 

Stubs and Skeletons   

 

RMI is ideally suited to applications which require a client to an application residing on another machine. Almost all application servers(servers that run applications as opposed to file servers that serve files or data) can benefit from RMI or a framework that allows RMI.RMI is the distributed component model for JAVA applications. COM/DCOM will be Microsoft’s equivalent. This means one Component(java Object) distributed in a network can be accessed by any  other Component on the network.

 

This is made possible by what are known as client-stubs and server-skeletons.

       

                     

 

 

The diagram above describes the RMI architecture on the lines of the OSI model. Suppose that there is a server object and a client object on two different machines. Let us further assume that the client object wants to invoke a method on the server object. To do this the client will need a reference to the object living in the server. Since both client and server are residing on different machines (different JVMs to be precise), an object reference on the server’s host is meaningless on the client’s host. This is where the client stub comes into picture. A client stub is another java object residing on the client’s machine (details of how this stub object finds it’s way to the client machine will come later) which acts as a proxy or surrogate for the object residing on the server.This means that the stub will contain all the methods that the server object has .However the stub’s implementation of these methods will be different from the implementation of these methods on the server object. Specifically, the stub’s implementation will be defined so as to pass the method arguments to the server through the Remote reference Layer via the transport protocol to the server. Since we are talking about java objects, the arguments and return types can be either primitive data types or objects. If they are objects , the stub must necessarily serialize all objects so that they can be sent over the network .Also the stub must be able to pass enough information to the skeleton (which is the stub’s counter part on the server) so that the skeleton knows which object’s method is being invoked. On the server side the server skeleton receives the request to invoke a method on the object actually residing in the server, formats the arguments into a valid method call and invokes the method on the object.If the method returns some value, this is returned via the same channel to the client, where the stub in turn returns this value to the client object.As far as the client object is concerned, it has transparently invoked a method on the server successfully. This process of collecting method arguments invoked on the stub and converting into a stream suitable for transport over the network is known as marshalling. Reconstructing a method call from a network data stream in its entirety is called un-marshalling.

 

So what is the big deal? Here also we are sending data across the network back and forth, albeit via method calls. One obvious advantage is that arguments passed through method calls require lesser overhead than transporting entire objects that contain these methods. Secondly we have not heard the full story.

 

The java.rmi.Remote interface

 

RMI provides an interface called Remote This is contained in the java.rmi package. If a class wants it’s objects to be accessible remotely, that class must implement this interface. Thus we call an object a Remote Object if it is accessible remotely. The Remote interface is an empty interface having no methods. It is a tag interface that tells the Java run time that objects of this class are remotely accessible. To make this class have it’s methods remotely accessible, the methods need to be declared in an interface that extends the Remote interface. The exact steps needed to do this are

 

1.      Declare an interface that extends java.rmi.Remote

 

public interface MyInterface extends java.rmi.Remote

 

2.      Declare methods that need to be accessed remotely in this

 

 

public interface MyInterface extends java.rmi.Remote

{

//Declare all methods here

public String getMessage()throws java.rmi.RemoteException;

//More methods

}

 

All  Remote methods must throw java.rmi.RemoteException

 

3.   Define a class that implements this interface.

Public class MyClass implements MyInterface

{

  //Variable definitions/Declarations

 //Constructors

 //Other methods

     public String getMessage()throws RemoteException

  {

  return new String(“Hello there!”);

  }

}

Now objects of this class, when passed as arguments in a remote method invocation are passed by reference and not by value. But How does a client find this object residing on some machine on the network?. An analogy of a library book shelf will help.

 

In a library , books are arranged on shelves according to certain rules, and, guidelines to locate books are provided to users. A user aware of these guidelines can locate a book quite easily.

 

In our discussion, the objects that we create of classes that implement Remote are like books. We need to put them in a place where a user can access them This place is the RMI registry. We name each of the objects we create and put the objects in the RMI registry. This process is called binding. Once an object is bound to this registry, a client can query this registry (known as looking up) for an object using the name of the object. The RMI registry is actually a naming service, in the sense that it locates objects bound to it and returns a reference to that object to any client that queries it. Having obtained the remote reference, the client can invoke methods on the remote object. Since the client always looks up the RMI registry for remote objects, it does not matter where the actual object is actually executing. This mechanism provides the location transparency that we talked about earlier. While looking up the client uses a simple URL formatted string to look up the object. For example if the RMI registry is running on a machine xyz.abc.org and an object by name “MyObject” is bound to it , the URL formatted string for this object will be

 

“rmi://xyz.abc.org/MyObject”

 

The above URL tells us that we are using the rmi protocol , the host name is xyz.abc.org and the object name is “MyObject”. Optionally we can specify a port number where we know the registry is listening.The default port of an rmi registry on windows95/98 is 1099.If we know that the registry has been started(we will discuss how to start the registry later)on port say 2005,then we specify the URL as

 

“rmi://xyz.abc.org:2005/MyObject”

 

Now how does this work? The object that we create is residing on one machine and we want that this object is somehow bound to a registry whose URL we know.(Current implementation of RMI does not allow the registry and Server object,ie the object implementing the Remote interface to be on different physical machines.A client can be a remote client,however)This can be achieved in two different ways. The first and the simpler option is for the class to use the functionality provided in the UnicastRemoteObject class

 

UnicastRemoteObject

 

 

In the class definition that we saw earlier,we make a slight modifification.We extend this class from another class found in the java.rmi.server package called the UnicastRemoteObject.That is we write our class definition as

 

public class MyClass extends UnicastRemoteObject implements MyInterface

{

 

//Methods and Variables go here

 

 

public static void main(String args[])

 

{

 

try

{

    MyClass obj=new MyClass();

 

/*.This is a Remote reference that has information  about where the actual object is residing in a network.This was made possible my the UnicastRemoteObject class that we extended.

 

Naming

 

The Naming (and the Regisrtry interface) class in the java.rmi package provides the bind(),rebind(),unbind() and lookup() methods to bind a Remote objects  to a registry or look up an object in the registry.Naming(or Registry) allows binding to local objects only..

 

Only Remote objects can be bound to the RMI registry.If the Remote object is located on xyz.abc.org listening at port 2005,we can bind this object named  “MyObject”  to the registry running on the local machine by using  the Naming class.*/

 

Naming.rebind(“rmi://xyz.abc.org:2005/MyObject”,obj);

 

/*You can also use Naming.bind if you know that you are binding the object for the first time. If you bind an Object to the name which has been already bound,an AtlreadyBoundException is thrown*/

 

}//end of try

 

catch(RemoteException re){ //do something here}

 

catch(MalformedURLExeption me){//do something here}

 

}//end of main

}//end of class

 

We said that the UnicastRemoteObject returns a RemoteObject stub. What actually happens behind the scenes is worth a look.

 

When you construct an Object of MyClass,the super class of MyClass,the UnicastRemoteObject class’s empty constructor is called. Inside this construcor another method of the UnicastRemoteObject is called,that is

 

RemoteStub rstub=UnicastRemoteObject.exportObject(RemoteObject obj)

 

The exportObject() method takes a RemoteObject as it’s argument.RemoteObject is an object that directly or indirectly implements the Remote inteface.In our case MyClass has implemented the Remote interface indirectly(through MyInterface).This method makes this object ready to receive client requests(i.e an Object of the Skeleton class is created with an anonymous port assigned to it.The skeleton contains a reference to the actual object of MyClass).It now returns a reference to this Skeleton and this reference is returned as the actual Object refernece.This  can be represented as

 

 

The Object Created by a call to it’s constructor is assigned the RemoteStub reference returned by exportObject().This is shownin the diagram below.This RemoteStub reference can be bound to a registry.The exportObject() method constructs both stub and skeleton,deploys the skeleton to receive requests on an anonymous port and returns the stub. Thus the object reference now actually points to the Skeleton which is capable of receiving requests from local and remote clients.Note also that once the object is exported, the actual MyClass object is only accessible through the Skeleton object whether local or remote.Remember this concept. It is this concept that is expanded by an EJB(Enterprise Java Bean ) container.An EJB server/container manages all the Beans in the container and provides proxy objects(EJBObjects) through which clients actually interact with EJBeans.More information on EJB is available here

 

 

 

Thus in a single call to the MyClass constructor,

·         MyClass Object is created

·         Myclass_Skel object is created to listen to client requests

·         A reference to this skeleton is assigned as object reference.which is nothing but the RemoteStub object.

 

Objects created by UnicastRemoteObject.exportObject() are non persistent objects that exists only while the JVM in which the server is running is alive.Once the Server exits, the remote object references are not valid.For persistent remote object references, objects must be created using the java.rmi.Activatable.exportObject().The Activatable class extends the java.rmi.RemoteServer.This class may also be extended to create persistent remote object references.All support for persistent object creation is available in the java.rmi.activation package.This topic is not covered in this discussion.

Back to Top

 

How Naming.rebind works.The java.rmi.registry package

 

Now we bind this to the registry using the Naming.rebind(or bind).What happens here?.

 

We supplied the URL of the registry and a name for our object as the rebind method’s first argument.Inside the rebind(or bind) method this is what happens.

 

There is package in rmi called java.rmi.registry which contains a single class LocateRegistry.This class has methods that can be used to locate a registry on the network(includeing local registry) and bind an object to this.Naming class actually uses these methods.For example, the rebind method of Naming class might do something like this.

 

//signature of rebind: rebind(String url, Remote obj)  throws 3 exceptions.The url is the location of the Remote Object.

 

then,

               public static void rebind(String url, Remote obj)

{

   Registry reg=LocateRegistry.getRegistry();

  //if the URL had a port number then,

  Registry reg=LocateRegistry.getRegistry(url,port);//url and port number of the registry.

reg.rebind(url,obj);

}

Thus we see that we could actually create a RemoteObject, convert it into a Server object , locate a registry, and bind the object to the registry with out using either UnicastRemoteObject or Naming.rebind.If we were to write this for our class ,

 

public class MyClass implements MyInterface

{

      public String getMessage()throws RemoteException

                  {

                              return(“hello there”);

                  }

 

public static void main(String args[])

        {

//create an object

 

           MyClass obj=new MyClass();

 

//To bind we need a RemoteObject.So get one

 

MyInterface remoteObj=(MyInterface)UnicastRemoteObject.exportObject(obj);

 

//get a registry object

         

Registry r =LocateRegistry.getRegistry(“localhost”,1099); //This is also the default

 

r.rebind(“ObjectName”,remoteObj);

}

}

                             

System.out.println(remoteObj.getMessage());//Valid

System.out.println(obj.getMessage());//Also valid on the local machine

 

The client can lookup the server object either through the Naming class(usnig the lookup() method ) or it can use a corresponding Registry.Locate and lookup methods.

 

Class Hierarchy

 

The main class hierarchy of key RMI classes is given below

 

                 

 

The complete code that makes an object of this class and binds it to the registry is as follows.This uses the more standard approach

 

     Import java.rmi.server.UniCastRemoteObject;

     Import java.rmi.Naming;

     Import java.rmi.RemoteException;

 

           

Public class MyClass extends UniCastRemoteObject implements MyInterface

{

  //Variable definitions/Declarations

 //Constructors.I

 //Other methods.

 

     public String getMessage()throws RemoteException

  {

  return new String(“Hello there!”);

  }

 

public static void main(String[] args)

 

{

//create a remote object

                  MyServer serverObject=new MyServer();

     

     //bind the object to a registry

try

{

Naming.rebind(“rmi://registryHost:1099/MYSERVER”, serverObject);

                        }

     catch(RemoteException re)

                        {

      re.printStackTrace();

                        }

     catch(MalformedURLException me)

                        {

     me.printStackTrace();

                        }

       }

}

 

If the rmi registry and server are on the same machine you can write the rebind method as Naming.rebind(“MYSERVER”,serverObject).

 

Running the program

 

·         First compile the Remote interface and the implementation class

javac MyServer.java MyClass.java

 

·         Then run the rmi compiler

 

rmic MyClass

 

This generates two additional classes

 

1.      MyClass_Stub.class and

2.      MyClass_Skel.class

 

These are the Remote stub and server Skeleton classes.

 

Stub is what the exportObject() method returns and this stub has a reference to the Skeleton Object.The Skeleton object in turn knows where the object is.

We bind the stub reference to the rmiregistry.

 

Passing remote references via method calls and return value

 

We saw in the earlier sections how to create remote objects and bind them to a registry so that clients can find them.What if we do not want to bind to the registry and still pass a refernce to a client.This can be done tby passing the remote reference(actually an exported remote reference) as method argument and /or return parameter.           

 

Every object reference that needs to be sent as a remote reference,must implement an interface that extends Remote, and , which declares the remotely accessible methods in this interface.Then this object will have to be exported.To do this we use the static method exportObject(RemoteObject obj) method of the UnicastRemoteObject class.Once the object is exported,it can be passed as arguments in method calls or return value from method calls..Needless to say we will have to generate the Stubs and Skeletons for this objects using rmic.

 

Thus in RMI, arguments and return values are passed in the following fashion

 

·         Primitive data types are passed by value.

·         Serializable only(non-remote) objects are passed by value.

·         Remote objects are sent by reference(regardless of whether the object is exported or not).

 

Thus if we do not export a remote object and pass this as method argument, a reference to the local object is passed to the remote client,and  as a result the client will not be able to find the object,since this object is not listening at any port for client requests.Actually, there is no skeleton to marshall arguments and return values for this object and as such no RemoteStub is created.

 

How to Lookup Remote objects

 

To lookup an object already bound to an rmiregistry, we use the static method  lookup of the Naming class.The signature of this method is RemoteObject lookup(String ObjectName).This means that we will have to type cast the RemoteObject to the type we want,which will be an object that implements our interface.Specifically we would want to cast to the Stub class of our implementation class.But in the code that we write we will not type cast to the Stub class; rather we will type cast to  the interface that we have defined in this way

 

SomeInterface a=(SomeInterface)Naming.lookup(“rmi://hostname/objectname:port no”);

 

For this to work , the stub of the class implementing this interface must be available in the local classpath of the client.This is not always feasible as the implementation detail of the interface can change and ideally clients should always get the latest implemetation of a any method in the interface.To do this we resort to Dynamic class loading.

 

Dynamic Class Loading

 

Using Dynamic class loading,it is possible to download a stub class(or any other class for that matter) at run 

 time.

 

To understand how this works, we need to understand the mechanism of RMI classloading

 

RMI classloading

 

When a Server Object  binds a remote reference to the rmiregistry, the rmiregistry tries to locate the stub in the local system classpath.If the stub class is found,then it lbinds the object reference as it is.However,if the rmiregistry is started from a directory that is not in the classpath, the registry looks at the java.rmi.server.codebase property which is set on the command line when the server is started.If this property is set and is valid,then the stub is loaded and it’s codebase is encoded as a URL and attached to the object reference that is bound to the registry. If the codebase property is not set,then an exception which displays an unmarshalling error similar to the one given below is thrown

 

         java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:

         java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:

         java.lang.ClassNotFoundException: AImpl_Stub

         java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:

         java.lang.ClassNotFoundException: AImpl_Stub

         java.lang.ClassNotFoundException: AImpl_Stub

        at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Compiled Code)

        at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:223)

        at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:342)

        at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)

        at java.rmi.Naming.rebind(Naming.java:165)

              at AImpl.main(AImpl.java:27)

 

To rectify this problem , specify the codebase at the command line as follows when the ServerClass is started

 

java –Djava.rmi.server.codebase=<URL of the directory containing the stub>  ServerClass.

 

For example if your stub class is located in C:\rmi\server ,then the codebase will be

 

java –Djava.rmi.server.codebase=file://c:/rmi/server/  ServerClass.Do not omit the trailing slash.

 

Another way to specify this is

 

java –Djava.rmi.server.codebase=file:///rmi/server/  ServerClass

 

There is one caveat here.In some OS , and JVM implementations the  file protocol may not work properly.In such situations use the http protocol.For this you need to start an http server like IIS or apache.Transfer your stub class to the document root of the server or one it’s sub-directories.Suppose your http server is running on a machine with IP address 128.1.5.25 and your stub class is in it’s document root,then you may set the codebase property in the command line is

 

Java –Djava.rmi.server.codebase=http://128.1.5.25/  ServerClass

 

 

 

Updated 26th August 2001

 

Aside:

 

A note on starting RMI registry

 

Suppose, all the classes viz., the Remote Interface, the implementing class, Stub and Skeleton are in a directory say, c:\RMI.Now assume that we start the rmiregistry from c:\.Also assume that the classpath is .;%JDK_CLASSPATH%.

 

Start the rmiregistry from c:\.

 

                         

.

Change to RMI  directory and invoke the Server.See picture below.

 

                        

              

 

The UnmarshalException is thrown. Why?. We have all the classes in this Directory and current directory is in the classpath.See the classpath variable in the above picture.

 

The problem is again related to RMI class loading.When rmiresgistry wants to bind the Object, it looks for the MessageServer_stub.class in the local classpath.For the rmiregistry, .; translates to C:\ because that is where we started the registry.As a result, it can not find the MessageServer_Stub class which it requires to serialize the stub and bind the object.This causes the UnmarshalException.

 

Now let us start the rmiregistry from C:\RMI and start the server.The Server will start.See picture below

 

                      

 

You can also do this by explicitly setting the classpath to point to c:\RMI and then start the registry from any directory.See the screen shot below.

 

                   

 

Acknowledgement:: This Aside was inspired by inputs from SteveMcdermott

 

 

Once this is done and if the rmiregistry is started from a directory that does not contain the stub class,the registry will load the stub slass from the URL specified in the codebase property and attach this URL to the marshalled byte stream.

 

On the client  side the default class loader(the class loader that loaded the client class will first examine the client’s class path to see if the stub class is available locally.If it can find the stub class it will use this class to create an object during the Naming.lookup() method.If it can not find the stub class , it will try to laod the class from the URL that it has received from the registry provided there is a Security Manager  installed.With out a Security Manager, the RMI runtime looks for classes only in the local classpath.A Security manager can be installed on the command line or by invoking the setSecurityManager() method of the System class.The only  security manager available for RMI from Sun is through the RMISecurityManager class.The RMISecurityManager is very restrictive and does not allow a stub object to access any system resource unless specific permission is allocated to it.This is done through creating a policy file which is nothing but a plain text file , often starting with a period and having an extension .policy.Following is an example of a policy file that grants socket and file permissions to a stub.

 

grant {

  permission java.net.SocketPermission "*:1099-65000", "connect, resolve";

  permission java.net.SocketPermission "localhost:80", "connect, resolve";

  permission java.io.FilePermission "http://localhost/", "read";

         };

 

This says that a stub can open a connection to any host at ports starting from 1099 to 65000.Also it gives specific permission to connect to localhost at port 80(port 80 is the default http port).This is required if you are downloading the stub from an http server.The first line is required for the Naming.lookup() to succeed.The file permission may not be necessary here,but this line allows the stub to read any file on the local host(Necessary if you are using file URLs).

 

This policy file was actually created using the policytool that comes bundled with JDK.

 

Once you have created and saved a policy file,you can the client with a command line as follows

 

java –Djava.security.policy=<full path of the policy file> Aclient

 

Where Aclient is the client class.If your policy file is named .client.policy and is in the same directory as your client class you can start the client by typing

 

java –Djava.security.policy=.client.policy  Aclient

 

You can set the security manager at command line by the following syntax

 

java –Djava.security.policy=.client.policy  -Djava.security.manager Aclient

 

Note that both server and client may need to set both the codebase and policy properties epending upon the roles they play in your application.An object can be both a client a server at different times depending upon who is invoking whose method,

 

Running the Client and Server from different JVMs

 

Since the codebase property is a URL, it stands to logic that stub classes may be placed on any machine on a network that runs an http server.The actual object itself could be on a different machine.The client of course can be anywhere on the network.As far as the client is concerned,it needs to know the location of only the registry.The registry can be located using the LocateRegistry class.The current implementation of the RMI requires that registries can only  bind,rebind and unbind objects which are running on the same host as the registry itself

 

·         Start the rmiregistry in one machine.Ensure that the rmiregistry does not have the stub class in it’s classpath.

 

·         Start the Server on the same machine with the codebase property(java.rmi.server.codebase) set to point to the codebase of the stub object.

 

·         Bind the server object(local)  to the registry by getting an instance of the registry usinig the LocateRegistry.getRegistry(String host) method.Use this registry object to bind the object.

 

·         Start the client by installing a security manager with the necessary permissions set in a policy file.

 

The required steps to dynamically download classes

 

Case 1:  Server and client on the same machine but  running from different directories.Stub stored in a Web Server Document Root

 

1.Copy Stub class into the document root of the web server.

2.Start the web server

3. Start the rmiregistry in another machine from a directory that does not contain the stub class.Use the following command

 

      start rmiregistry –J-Dsun.rmi.loader.logLevel=VERBOSE if debugging information is required.If not, use:

      start rmiregistry

 

4. Start your server(the class whose object you are binding to the registry).Use the following command from a directory that contains the

    Server or from any other dirsctory using the  -cp option.Example

 

      Java –cp <path to your class files> -Djava.rmi.server.codebase=http://URL of thhe  web server:port no/  ServerClass

 

      For example on a Weblogic server running on mac-25  listeneing on port 7001,you would use

 

     Java –cp <path to your class files> -Djava.rmi.server.codebase=http://mac-25:7001/  ServerClass

 

     You may also use a dotted IP address such as 128.1.5.25 instead of mac-25.

 

       A space after the forward slash where the URL ends is mandatory

 

5.      Ensure that a Security manager is present on the client code.That is, before the lookup method is executed , the following line of

     code should be executed.

 

         System.setSecurityManager(new RMISecurityManager());

 

6.      Create a policy file using the policytool.Give SocketPermission as connect and resolve.Save the policy file .Normally a .policy

      extension is used..If the policy file is named mypolicy.policy,the command to start the client is

     

               java –cp <path to client class>  -Djava.security.policy=<path to the client directory>/mypolicy.policy ClientClass

 

 

Case 2:  Server and client on different machines .Stub stored in a Web Server Document Root

 

·         Ensure that the web server document root contains your stub class and that the web server is started

 

1.      Make sure that the registry and the implementaion class are started on the same machine.Also take care of point 3 of case 1.

2.      Start the registry and server using the same commands as in case 1.

3.      Follow step 5. and 6

4.      In step 6 , since the registry is running on a different machine,ensure that in the Naming.lookup or registry.lookup,you pass theURL of the rmiregistry and the name of the object that is being looked up.That is , if the registry is running on a machine on the local intranet and has an Ip address of 128.1.5.25 and the object name is IBM, the url that you pass to lookup should be

 

Naming.lookup(“rmi://128.1.5.25/IBM”);

 

       

On the client side you must atleast have the Client Class and the Interface of the object that you  are trying to look up.Stub class for this object can be dynamically downloaded as well as any other class(for remote objects obtained as return values or passed as parameters through methods)

 

Garbage Collection of Remote Objects

 

RMI run time employs a simple algorithm to keep track of live remote objects. Internally the server  keeps a count of all live references to a remote object. When the reference count for a particular object becomes zero, that object is marked for garbage collection. This happens when the lease on the object reference held by the client expires. Thus if a client needs to hold on to  a Remote Object reference, it must make additional calls(called dirty calls) on the object to refresh the lease. Once the lease expires, that object is marked  clean. A clean object can be garbage collected. The lease time can be set using the system property java.rmi.dgc.leaseValue.The value is set in milliseconds and defaults to 10 minutes, sufficient in most situations. However, the possibility does exist where a client finds that the Remote Object , whose reference it was holding, has suddenly disappeared. In such cases ,  a java.rmi.ConnectException is thrown. You need not worry about Objects bound to the rmiregistry from disappearing as the registry, itself being a Remote Client to the Server Object,  will always keep a live reference to the Object. The same however can not be said about Remote references,  either returned from a Remote method  or passed as parameters.

 

There is an interface , the java.rmi.server.Unreferenced, that a Remote object can implement to get notified when the object is clean and becomes a candidate for garbage collection. This interface contains a single method , public void unreferenced() , which the implementing class should override. Note that the Distributed Garbage Collector calls the protected void finalize() method  of the java.lang.Object class before actually collecting the object.

______________________________________________________________________________________

Geocities Guest Book     :                                                View Guestbook

 

Enterprise Java World Guest book                                 : Sign     View                     

 

Copyright  ă Sundar Rajan 2000-2001

 

 

Back to Top