Jeevan has posted 2 posts at DZone. View Full User Profile

Back to Basics: RMI Revisited

07.08.2008
| 17208 views |
  • submit to reddit

Parameter Passing

With RMI we have three types of parameters :
  • Primitive parameters : these are passed by value , just like any other primitive parameter.
  • Object parameters : Since references in one JVM are meaningless in another JVM, objects are serialized and passed by value. So changing the properties of an object in the remote JVM does not make those changes visible to the local JVM.
  • Remote Parameters : Remote parameters are parameters that happen to be remote objects themselves. When a remote object is used as a parameter or a return type, the JVM passes the stub to the remote object and not the remote object itself. Under the covers the JVM checks the parameters and return types. if any of them is an instance of Remote, then its stub is fetched, serialized and sent across, instead of the actual remote object. this rule applies to all references, including say, retuning 'this' from a remote object.

Distributed Garbage Collection

RMI provides a distributed garbage collector to collect remote objects. Garbage collection in RMI is more complex because there may not be any local references to an object. Internally, the JVM keeps track of clients requesting access to a remote object, and marks that object as dirty. When the remote reference is dropped, the object is marked clean; all clean objects are eligible for garbage collection when the distributed garbage collector runs. In addition to the reference counting mechanism, there is a lease mechanism, which basically means that even if a client requested access to a remote object, unless the client is actively using the connection, the connection has a timeout associated with it (defaults to 10 minutes), and when the timeout has been reached, the object is marked clean. Like the finalize() method, RMI has an interface Unreferenced, with a single method unreferenced() that is invoked when there are no more clients holding a live connection to the remote object. Remember that the registry itself is a client to the remote object and the unreferenced method on a remote object(should it choose to implement Unreferenced) will not be invoked if the registry is holding a reference to it.

Dynamic Class Loading

Normally the clients need to have the remote interface type's class files available on the client JVM so that they can use it to cast the resulting stub from from a look-up and invoke methods on it. However, RMI supports dynamic class loading as an alternative to this static approach. Dynamic class loading in RMI works similar to applets or JNLP; here a system property for a codebase is set and the required class definitions are downloaded on demand from that code base. The property is java.RMI.server.codebase and is a URL that can be accessed with file:// ftp:// or http:// protocols. note that though we say "client JVMs download the class definition" its not restricted to client JVMs; Server JVMs can also use a code base to download other remote object definitions or client side classes for callbacks. When an object is bound in the registry, the code base is also saved with it.When a client requests a remote object, the registry returns a stub to the remote object, and the client JVM looks for the class definition of the stub in its CLASSPATH and if it does not find it there, it uses the code base from the registry, to download the definitions. RMI has its own Security manager, the RMISecurityManager and the VM will not download any files unless the security manager is present.

Object Activation

One of the downsides to RMI is that the remote objects have to be accessible at all times, including when clients are not executing or requesting their services, and eats up a lot of resources. To solve this problem object activation was introduced to RMI. This is similar to having the remote objects on an "on demand" basis, and can be though similar to lazily instantiated references. All the magic happens in the Remote reference layer, and the stub given to client is not connected to a live remote object or its skeleton, instead its connected to the activation system, that transparently makes resources available when the stub is actually being used. The activation system is a complex ecosystem and core t it is an RMI daemon 'rmid' which is able to start new virtual machine instances for the required remote objects when required.

Activatable Remote objects extend from the abstract class Activatable (no, this is not an interface and not from the usual UnicastRemoteObject). The process of registering an activatable remote object is also considerably different, though the client does not see any difference. The steps are :
  1. Install the SecurityManager - RMISecurityMananger
  2. Create an ActivationGroup - which is an object that keeps a collection of Activatable objects
  3. Create an ActivationDesc - or ActivationDescriptor instance, that provides all information to the rmid (the Activator) to create a new instance of the implementation class.
  4. Register the remote interface with the Activator - Activatable.register() registers the Remote interface with the rmid, the activator.
  5. Bind the stub that was returned as a result of register() with the RMIRegistry.

once this rig is setup, Activation process works like this :
  1. The Stub for the Activatable object contains special information like the ActivationID that identifies an Activatable.
  2. The stub uses this ActivationID to call on the Activator (rmid) to activate the object.
  3. The activator (rmid) uses the ActivationDescriptor to find the JVM in which the object is to be activated.
  4. The activator locates the ActivationGroup and if the ActivationGroup does not yet exist, then a new JVM is created for the AcivationGroup to run in and the request for the object's activation is forwarded to the ActivationGroup.
  5. The ActivationGroup loads the class and creates a new instance of the remote object.
  6. The live reference of the real remote object is returned to the Activator , which records the ActiovationID and reference pairing and the live reference is returned to the stub.
  7. The stub now forwards all method invocations to the remote object via the live reference.

Published at DZone with permission of its author, Jeevan Joseph.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)