Overview

Architecture

Implementation Notes

Javadoc

Known Issues

Specification Issues

Team





Package name java.rmi

Sequence Diagrams

  • Object Exportation
  • Remote Call Invocation
  • Remote Call Execution
  • Distributed Garbage Collector - Overview
  • Distributed Garbage Collector - Server Side
  • Distributed Garbage Collector - Client Side
  • Transport Layer - Call Invocation
  • Transport Layer - Fallback Connection Strategy
  • Transport Layer - MultithreadedServer
  • Transport Layer - StreamServerConnection
  • Transport Layer - SingleOpServerConnection
  • Transport Layer - StreamClientConnection
  • Transport Layer - SingleOpClientConnection
  • Object Exportation

    This diagram explains the procedure that ocurrs when a new object is to be exported. Initially the user calls one of the static export methods of the Class UnicastRemoteObject or a new UnicastRemoteObject is created. The RemoteReferenceManager is in charge of the management of the exported objects, so the UnicastRemoteObject export method delegates this task to the RemoteReferenceManager singleton. In turn the RemoteReferenceManager creates a new ObjID for the object which uniquely identifies it, and the calls the export service of the TransportManager. The TransportManager creates a new ServerSocket and a new thread listening for incoming calls in the ServerSocket, and it returns an Endpoint which it is used to create the stubs for the exported object. With the Endpoint instance a new ServerRef constructed, and holds Reference to the actual object. Finally the RemoteReferenceManager updates several internal tables, and returns a new Stub created for the object. This way, we have a new Stub (possibly cached) for the exported object, and a listening thread waiting for new connections on that object.

    Remote Call Invocation

    This diagram represents the procedure by which a RMI user invokes a method on a Remote object. Initially the Client invokes a method on a Stub which references to an exported Remote object. The Stub calls the RemoteReferenceManager invoke method. The RemoteReferenceManager must send the needed information to the corresponding server. For that purpose it uses the services provided by the TransportManager singleton. Specifically it calls the invoke method on the TransportManager instance, which will send the ObjID, the method hash and the argumets to the specified Endpoint, and it will wait for the response from the server. Finally when the return value comes back, it is given back to the calling client.

    Remote Call Execution

    The execution of a remote method on the server begins when a new incoming call message is received on the listening ServerSocket of the exported object. Then the ObjID, hash of the method and parameters are received. The concrete execution of the method it should be done by the RemoteReferenceManager via the executeCall method. The RemoteReferenceManager lookups the ServerRef corresponding to the received ObjID, and executes the method identified by the hash on the concrete object refereed by the ServerRef. Once the method has been executed the result is sent back through the TransportManager to the calling process.

    Distributed Garbage Collector - Overview

    The garbage collection mechanism specified for RMI is similar to that implemented for Modula3. Basically this mechanism guarantees the persistence of remote objects as long as a client with a reference to that object exists. This issue is acknowledge through the use of Reference Counting. An exported object can only be unexported by the DGC when: 1 There are no more remote references to the object in any client. 2 There are no more (Strong) references to the exported object in the servers JVM. 3 There are no more Remote references to the object in the servers JVM. 4 The object has not already been explicitly exported by the servers process. The first issue is acknowledge through the use of reference counting for the Clients holding references. The second and third conditions are acknowledged through the use of WeakReferences and ReferenceQueues on the server side. Finally the fourth issue is handled by the unexportation mechanism.

    Distributed Garbage Collector - Server Side

    As mentioned before the server side of the Distributed Garbage Collector must hold reference counters for every exported object. For this purpose any client receiving a reference to an exported object sends a “dirty” call to the server for that object indicating that the reference count of that object must be incremented. Similarly when an client will no longer use a remote reference sends the server a “clean” call indicating that the reference counter should be decremented.



    While a remote reference to an exported object exists in any client the server must guarantee that a Strong reference to the exported object is still reachable. Although the DGC must not interfere with the java's native garbage collection mechanism. If a strong reference for every exported object was hold in the DGCServer, then that object could never be collected. To avoid that we have created a changing reference. The DGC holds one of those changing references, which is a strong reference when the reference counter for the refereed object is bigger that 0, and is a weak reference when the counter reaches 0.



    Summing up: Data Structures used: Note: this is a conceptual scheme, the actual structures differ from the ones showed below. ReferenceQueue: Holding WeakReferences for every exported object, only used to cleanup an object when it is locally garbage collected . HashMap: Used to unexport an object. HashMap, ObjID>: Used to cleanup when an object has been garbage collected. HashMap: Used to know how many Stubs exist for an exported object. And to guarantee that at least one Strong reference exists when the counter is greater than 0. Threads: Cleaning Thread: This special Thread is needed to inspect the Reference Queue to unexport objects as they are “locally” garbage collected. GC Thread: As the garbage collector only runs when there is need for memory, remote objects out of scope would need to wait untill the memory becomes low enough to get garbage collected. In fact if the server does not grow the heap the GC could never run. For that reason we needed to add this thread that run the GC periodically.

    Distributed Garbage Collector - Client Side

    When an object is transferred during a remote call invocation, it is deserialized by the Java serialization mechanism, and the resolveObject() method is invoked on the RMIObjectInputStream class. If the received object is a stub (either a proxy stub or a stub created by rmic), this method gets the instance of the Client Distributed Garbage Collector (which is a singleton object) and sends the received stub to it, calling the getStubInstance(Remote) method. The Client DGC will search for a previously received instance of the stub, in order to keep only one instance for that stub in the client. If an instance of the stub already exists in the client, that instance is simply returned and the new received stub is replaced by the pre-existent one. The received stub is then discarded, and the client application receives the old-unique instance of the stub. If the received stub is the first instance of that stub in the client, a dirty call is sent to the Server Distributed Garbage Collector of that stub, in order to get the appropriate Lease for it, which will grant the remote server will not be garbage collected in the server.



    After the lease has been received, a dirty call must be scheduled in order to renew the Lease before its expiration. The dirty call is then scheduled in a task of a Timer object, which will send the dirty message to the Server Distributed Garbage Collector every half the time granted by the Lease returned by the server.

    A weak reference of the stub is stored in a referenceQueue, which is being monitored in another thread, and which will notify when the stub is collected by the local garbage collector. Finally, the stub is cached inside a WeakHashMap, which will not prevent for the stub to be collected by the local garbage collector, but will hold a reference which will be used the get and return a strong reference to the unique instance of the stub, when another instance of the same stub arrives to the client, as stated before. When all the strong references for the unique instance of the stub have been lost, the stub will be suitable for local garbage collection. When this happens, the Client DGC will take notice via the referenceQueue, and then it will send a clean message to the Server DGC, in order to let it know that there isn’t any more references to the remote server in the client.

    Transport Layer - Call Invocation

    When an invocation request from a stub (see Remote Call Invocation diagram explanation) is executed on the TransportManager, a ClientConnection is requested from the ConnectionPool. If there is not any available connection to reuse, a new connection is created and returned. The returned connection will be a concrete subclass of the abstract type AbstractClientConnection, (either a SingleOpClientConnection (http), or a StreamClientConnection (direct JRMP)) depending on the reachability of the server, and determined by the transport’s fallback mechanism. The “invoke” method is then executed over this connection, which will forward the request in the concrete method “methodCall”, which is specific for each kind of connection. When the invocation has returned, the connection is checked in order to determine if could be reused in the future; if is a “reusable” connection (stream), it will be returned to the pool, otherwise (http), it will be closed and discarded. Finally, the object returned by the connection’s “invoke” method is returned to the caller.

    Transport Layer - Fallback Connection Strategy

    This scheme presents the default Fallback mechanism RMI uses to connect to to a server. Initially the client attempts a direct TCP/IP connection to the server. If that connection fails it attempts to create a HttpSocket specifying the hostname and the port of the Proxy through which the connection must traverse. If the direct HTTP connection fails it attempts to create a connection through the same Proxy assuming a CGI script which forwards RMI requests is loaded on the server machine.

    Transport Layer - MultithreadedServer

    When a connection is accepted at the server a new ServerConnection is created to handle that connection. This connection is created using the ServerConnectionFactory. Then the serve method is called on the AbstractServerConnection wich actually handles the request. The AbstractServerConnection can be an instance of StreamServerConnectionFactory, or SingleOpServerConnection, depending on whether the client is using a direct or an HTTP connection. See StreamServerConnection and SingleOpServerConnection explanations.

    Transport Layer - StreamServerConnection

    The StreamServerConnection initially reads the contents of the message sent and it encapsulates them on a Message instance. Afterwards checks which kind of message was read and handles ir accordingly. Each kind of message has a special private method that handles it. It is worth noting that all the interaction with the concrete messages is handled with the appropriate protocolHandler. Also is important to note that this version of the ServerConnection sends and receives more than one message through the same Conncetion. In fact receives the DGCAck before quiting the execution

    Transport Layer - SingleOpServerConnection

    Refer to StreamServerConnection for explanation on this diagram. The difference between this diagram and the StreamServerConnection - Design Version 4 is that at most one message can be sent and received, thus eliminating the possibility to receive a Ping message and to send the DGCAck through this connection.

    Transport Layer - StreamClientConnection

    This sequence represents the concrete implementation for the “methodCall” method described in the TransportManager.invoke sequence, for the specific direct JRMP “StreamClientConnection” class. In this connection type, the connection should be previously established via the establishConnection method, which sends and receives the necessary handshake information to sets the channel ready for call invocation. The call data is written through the ClientProtocolHandler, and then the output stream is flushed. The response from the server is read and the returned ReturnMessage is inquired in order to determine if a DGCAck message should be sent. If this is true, a DGCAck message is sent over the same connection. Finally, if the response from the server was an exception, the received exception is unpacked and thrown to the client; otherwise, the received object is returned to the client.

    Transport Layer - SingleOpClientConnection

    This sequence represents the concrete implementation for the “methodCall” method described in the TransportManager.invoke sequence, for the specific JRMP through HTTP “SingleOpClientConnection”. This connection type is characteristic for its single round trip with the server, since all exchange is made through HTTP messages. Initially the call request is delegated to the ClientProtocolHandler, which is in charge of sending the call data to the underlying stream. A flush() invocation will send the HTTP message to the server, and then the answer from the server is read through ClientProtocolHandler’s methods again. If the response from the server is a stub (or contains one or more stubs), a DGCAck message is sent again to the server; for this purpose a call to the acknowledgeDGCAck method of the TransportManager (which handles this task sending the message in a different connection) is made. If the response received from the server is an exception, the exception is unpackaged and thrown to the client. Finally, if the response from the server is an object, the object is returned.



    Copyright © 2005-2006 Instituto Tecnológico Córdoba
    Last updated: Mar 17, 2006