Java features a library package for socket programming since its first release in 1995 and support for distributed programming appears one year later with the addition of a distributed object model [128], mainly an object-oriented version of RPC (see Section 2.2.2).
Its integration in the Java run-time environment is achieved through the extension of the exception handling and security mechanisms and the addition of a distributed garbage collector.
2.3.1
Distributed Objects
Java RMI provides language-level support for distributed objects.
Under the term distributed object (or remote object or server object) we mean an object which resides in a separate address space and methods of which can be called remotely (a remote call is issued in an address space separate to the address space where the target object resides).
By convention, the code issuing the call is referred to as the client. The set of methods which implements one of the server object’s interfaces is sometimes designated as a service that this object provides. Similarly, the process in which the server object is located is referred to as a server.
An important goal of the client and server abstractions is to make it transparent how far the client and server spaces actually are — whether they reside on the same machine6 or on different network nodes —.
The design goal for the Java RMI architecture was to create a distributed
object model (JDOM) that integrates naturally into the Java programming
language and the local object model (JOM). The RMI architecture is based on one important principle: the definition of behavior and the implemen- tation of that behavior are separate concepts. Specifically, the definition of a remote service is coded using a Java interface and its implementation is coded in a class.
Similarly to Java objects, remote Java objects are passed as arguments of method invocations, and can be cast to any remote interface allowed by the JOM. Changes to the invocation semantics of the remote objects in- clude passing non-remote arguments of remote methods by copy, passing remote arguments of remote methods by reference, specialized seman- tics of several methods of the Object class, and more complex exception handling required by remote objects.
6
2.3. DISTRIBUTED PROGRAMMING IN JAVA 41
NOTE
While Java RMI does preserve the regular Java invocation syntax, pa- rameters of remote operations are treated differently from those of local operations. Remote passing is done as follows:
- If an actual parameter has a primitive type it is passed by value. - If an actual parameter has a reference type and its class implements
the Remote interface, it is passed by reference (the local reference being replaced by a network reference).
- If a class does not implement Remote but rather implements the
Serializableinterface, the object is passed by value (using serializa-
tion).
- If a class implements neitherRemotenorSerializablean exception is raised. Java arrays are serializable by default.
2.3.2
Distributed Exception Handling
All methods of a remote interface, an interface that extendsRemote, must listRemoteExceptionin their throws clause7. Additionally, they can throw any other Java exceptions and the client code can catch them.
RemoteExceptionis the common superclass for many communication-
related exceptions that may be thrown during the execution of a remote method call. They can be organized into several categories depending on the performed RMI operation; for brevity, we give just one example per category:
Naming exceptions A NotBoundException is thrown when attempting to
look up a name that is not bound.
Export exceptions A StubNotFoundException is thrown if no valid stub
class was found for a remote object to be exported.
Calling exceptions ANoSuchObjectExceptionis thrown when attempting
to invoke a method on an object that is no longer available.
Return exceptions An UnmarshalException can be thrown while unmar-
shalling the parameters or results of a remote method call.
2.3.3
Distributed Garbage Collection
Thanks to garbage collection Java programmers don’t spend their time chasing memory management errors; the increase in code reliability and
7
productivity largely compensate the run-time costs associated with that mechanism. Garbage collectors (GC) implemented on a single VM are typically designed to maximize the performance of applications at the expense of predictability.
As opposed to the classical techniques used in single address space, garbage collection in distributed environment is a more complex issue that has been the subject of much research (e.g. Ferreira and al. [42]). In particular, coordination becomes essential for the management of dis- tributed system resources. In Java the main difficulty with distributed garbage collection is that object references can cross node boundaries.
Futhermore garbage collection in Java is not guaranteed to be timely8. Indeed, as garbage collection is potientially expensive, the JVM is free to do it only when necessary [118].
In contrast to the local garbage collector, the Java RMI distributed garbage collector’s (DGC) behavior is well defined and reliable with re- spect to its timing. The DGC employs a lease mechanism for remote references. All remote references are leased to clients for a default pe- riod of time. The client VM must request a new lease before the period runs out. Otherwise the server considers the remote reference to be dead and releases the corresponding remote object to the local GC for potential collection.
The RMI system provides a reference counting distributed garbage collection algorithm based on Modula-3’s network objects [13]. Thus, activity on nodes must not be suspended while collecting, as it is the case with the traditional mark-and-sweep scheme.
NOTE
The RMI system uses the broker approach which evaluates the num- ber of live references: it keeps track of the live TCP/IP connections. Basically, each registration of a remote reference in the RMI Registry implies also one live connection. If the number of live connections reaches zero, the server object is handled as if it was a local object in the server VM and thus being a subject of the standard local garbage collection process.
If the number of live remote references to the remote object in the current JVM (before deserializing this one) had been zero, then the client-side DGC implementation will attempt to call the server-side DGC once, synchronous with the deserialization, in an effort to main- tain referential integrity (if that attempt fails, retries will only be at- tempted in the background). Deserializing a remote stub behaves in this respect similarly to unmarshalling one as part of a remote call’s arguments or return value.
8