Overview

Architecture

Implementation Notes

Javadoc

Known Issues

Specification Issues

Team





Package name java.rmi

Implementation Notes

The code uses J2SE 5.0 features, such as generics, so it requires 5.0 VM and libraries (i.e.: java.util.concurrent). It has been tested against Sun SDK, removing the original java.rmi.* and replacing it by ours.

  • UnicastRemoteRuntime Implementation Ideas
  • rmic Implementation Ideas
  • GarbageCollector Implementation Ideas
  • Registry Implementation Ideas
  • TransporManager Implementation Ideas
  • Activation Implementation Ideas
  • Note: These are a set of ideas elaborated during development meetings and used as guidelines for the construction of the successive Design Versions, or as base for the generation of new and more accurate ideas and procedures. The evolution of the project iterations will not be reflected by these ideas since they will not be properly corrected or adapted to reflect the current or final state of the design. These ideas do not represent in any way the final design or implementation of the project, and are stored and maintained only for reference and traceability purposes.


    UnicastRemoteRuntime Implementation Ideas

    05/10/2005 - Gonzalo Ortega

    Exportation of a Remote Object

    The exportation of UnicastRemote objects could be made by 2 different ways:
    a) Extending UnicastRemoteObject (in this case the exported object is a RemoteObject itself)
    b) Using static method exportObject (in this case the exported object could be of any kind, and only implements the Remote interface.)

    During exportation, we have only this data:

  • a reference to the object being exported. I will call it the “real” server. (the only thing we know for sure of this object is that it will implement the “Remote” interface, that is an empty interface… almost nothing)
  • an integer that indicate the port where it will be exported.
  • In both cases a) and b) during exportation (when we call the exportObject method, or the constructor of the UnicastRemoteObject) we could create an object “ServerRef” (implements the ServerRef interface, and the RemoteRef interface, because it will extend our implementation of RemoteRef) to store useful data like:

  • hostname (string?)
  • port (int?)
  • an ObjID (object that identifies our ServerRef univocally inside the VM)


  • Note: this data will be stored maybe as attributes of the RemoteRef object, because they will be sent to the client over the wire
    Note: maybe is a good idea to store all the “socket” information in a separate object inside the RemoteRef object, with the references to the CustomSocket factories

    The ServerRef object will contain a hashtable that holds the relations between the objects “Method” and their corresponding MethodHash. This table could be filled using java’s reflection mechanism to inspect all the methods of the real server object.

    Note: only the methods of the “Remote” interfaces implemented by the “real” server object. The “real” server object could have methods that won’t have to be exported

    In the ServerRef we need to store also a “real” reference to the “real” server object, so we could use it when we need to “execute” the methods stored in the hashtable. The ServerRef object will also implement a method like:

    static Object invoke (MethodHash,Arguments)

    And calling this method with the appropriate parameters will cause the invocation of the method referenced inside the hashtable (by the MethodHash), in the reference to the “real” server object, and using Arguments (maybe an array of Objects) as parameters of the invocation. (Note: this invocation is done via java’s reflection mechanism)
    Now we have:

  • a ServerRef object containing all the methods and their hashes of the “real” server, and ready to invoke a method in it.
  • a RemoteRef object (the ServerRef and RemoteRef are the same object) containing all the data needed to “contact” the ServerRef object (hostname,port, and an ObjID)
  • an integer that indicate the port where the object will be exported.
  • Having this object “ServerRef” ready, this object will be sent to a “UnicastExportedObjectsManager” (Note: it could be a class, or a group of classes) via a method like:

    static Stub??? export (ServerRef, port);

    This “UnicastExportedObjectsManager” will store hashtables containing all the objects exported by this VM. In one of this hashtables, this Manager could store the port used and a Collection (Vector, or Hashtables?) of ServerRefs that are exported in that port.
    When the ServerRef is stored in the hashtable with the port as index, the ExportedObjectManager will request to the Transport layer the creation of a SocketServer in that port. The transport layer will know if there is a ServerSocket created in that port yet, and if there isn’t, it will create a new one in a separate thread (because the ServerSocket locks waiting incoming requests, and we need that the request of creation of the ServerSocket return immediately to continue the exportation process).
    With the Transport layer “listening” in the desired port, the ExportedObjectManager will create a new stub for this ServerRef (starting from the class generated by rmic, or via a dynamicProxy) and will store this stub in another hashtable for future use.
    Finally, the ExportedObjectManager will return a reference to the stub created, finalizing the exportation process.
    The ExportedObjectManager will also implement a method like:

    static Object invoke(port,ObjID,MethodHash,Arguments);

    that method will be called by the Transport layer when a “Call” request arrive to a ServerSocket listening in that port. When is called by the Transport layer, this method will look inside the table by port and ObjID, and will recover a reference to the original ServerRef stored, and will call the method invoke inside the ServerRef, via the previously defined method:

    static Object invoke (MethodHash,Arguments);

    firing the invocation of the method in the “real” object.

    Remote Method Invocation from the client side
    The client has a stub holding a RemoteRef object inside. The stub is a proxy object implementing exactly the same interface that the “real” server object. All its methods will do the same, they will obtain the method hash for the method currently being invoked and they will call the method “invoke” in the RemoteRef object, passing the method hash and the parameters.
    The invoke method of the object implementing the RemoteRef interface will call a method in the Transport layer like:

    static Object makeCall(host,port,ObjID,methodHash,Arguments);

    The transport layer will create a socket bound to the indicated host and port (there should be a serverSocker listening in that port, created when we exported the server object) and the ObjID, methodHash and Arguments will be transferred to the server (Serializing them, when necessary), with a flag indicating a “Call” package.

    Note: The transport layer used is very simple at this moment, and it will grow gradually in order to support the complete RMI protocol.

    The Transport layer in the server will dispatch the request to the ExportedObjectsManager, and it will make the invocation in the “real” object as we described above.




    RMIC Ideas

    10/10/2005 Daniel Gandara

    When reading the specification in deep detail we found it to be very vague with many subspecified things; we also realice about the complexity behind evolution inside the spec, many deprecated things are still supported, and that adds a huge complexity to the design if you plan to support them. Now first estimation and quote for the project start to looks too optimistic... We'll have to review it.

    18/10/2005 Daniel Gandara

    Looking at the package we see that is could be decoupled in two pieces: - Framework - Provider we see that there is a general (framework) functionality for the package, which needs for "services" to do the tasks; all transport is an example of this, we also see some interfaces which are part of the spec but are implemented by none of the public classes... this looks extrange, looks like some implementation details showing on the spec...

    20/10/2005 Daniel Gandara

    Should we implement rmic? or not? the specification on section 5.11 and section 8 makes reference to rmic, but basically it just says that there is a tool named rmic who generates code for stubs and skeletons.


    "5.11 Stub and Skeleton Compiler The rmic stub and skeleton compiler is used to compile the appropriate stubs and skeletons for a specific remote object implementation. ..."
    "8. Stub/Skeleton Interfaces This section contains the interfaces and classes used by the stubs and skeletons generated by the rmic stub compiler. ..."

    The questions at this point are:
  • 1. rmic generates code (source code) for both stubs and skeletons which make use of public api, but following a given logic and sequence, which is not expressed anywhere on the especification document.
  • 2. do all rmics (IBM, BEA, Sun, ...) generate the same source output?
  • 3. should we implement our own rmic, so that stubs and skeletons follows our way to handle the functionality?
  • 4. Is rmic -and its outputs- extension of the specification? the spec does not say that, at least not as clear as this...

  • The best way to give some light on this is to install several JDKs and check their output from rmic, for a given example, in order to see if they are different or not.

    25/10/2005 Daniel Gandara

    rmic's outputs (stub's source code) from different vendors (ibm, sun, bea) are exactly the same; same code, same comments, same amount of bytes... So this is quite extrange, and looks like all of them are using the same code for rmic or the same tool. This make us think that rmic outputs are an extension to the especification, which is a good point because of:


  • a) we do not have to implement rmic since it is a tool and its out of the scope of the java.rmi package.
  • b) we have more information about the package and its expected functionality, since the outputs from rmic -source code of stubs and skeletons- give an exact detail about how the api must be used.


  • on the other hand, this adds more constraints to the implementation, because not only do we have to implement the api, we must use it in a certain way...

    GarbageCollector Implementation Ideas

    RMI GarbageCollector Mechanism

    Note: These are a set of ideas elaborated during development meetings and used as guidelines for the construction of the successive Design Versions, or as base for the generation of new and more accurate ideas and procedures. The evolution of the project iterations will not be reflected by these ideas since they will not be properly corrected or adapted to reflect the current or final state of the design. These ideas do not represent in any way the final design or implementation of the project, and are stored and maintained only for reference and traceability purposes.

    07/10/2005 - Gonzalo Ortega

    The consulted bibliography (O’Reilly, pag 322) and the ObjID API specification (Sun) suggest that the RMI GarbageCollector is another RMI server, implementing the DGC interface and there is only one DGC per VM. When a stub is deserialized in a client (received from the registry for example) it will contact to the DGC of the server host, noticing that a new reference for the server object exists in the client. How? Maybe during stub instantiation, it is “subscribed” in some way in the local DGC, and then is the local DGC who contacts the server DGC to request the lease… this seems probably because the leases are renewed automatically in time, without the apparent stub intervention. If was the stub itself who contacts the server’s DGC, they will have to launch another thread to renew the leases, and this seems improbable.

    11/10/2005 - Gonzalo Ortega

    Problem: if the RMI Garbage Collector is an ordinary RMI server… in what port is exported? Who exported it? And when? When the first object is exported? In an anonymous port? (seems improbable, because the client contact it without any information about the port) One approach could be that the DGC in the server is automatically exported when the first server is exported, and the DGC is listening in “ALL” the ports of the server. In other words, the DGC is exported together with any exported object, in every port where an exported object is listening. In this way, the client only needs to know the IP of the server, and then sends the DGCs messages to the same port where the remote server is listening, but with the special ObjID for the DGC. Then the network layer or the remote reference layer in the server could send the received message to the appropriate destination (remote server, or DGC) This kind of implementation also allows the clients (or the client’s DGC) to contact the server’s DGC without using any kind of stub (static or dynamic), the messages are simply sent to the IP and port of the remote server, with the special ObjID, and then are re-routed by the RMI runtime to the destination. Other idea is including the DGC port of the current VM in all the stubs exported by the RMI Runtime running in that VM, in that way, the RemoteRef in the client could use the IP of the exported server and the DGC port included inside the RemoteRef data, instead of the port of the exported object.

    23/11/2005 – Gonzalo Ortega

    As talked in successive meetings, these are some new or complementary implementation ideas for the distributed garbage collection:
    At the time, the ServerRef implementation holds a reference to the exported object for dispatching remote calls; this reference should be a Weak reference, in order not to avoid the collection of the object by the local garbage collector.
    The distributed garbage collector will hold the counter of how many remote references there are for each remote object exported in the local RMI Runtime. This counter should be incremented by received “dirty” calls, and decremented by received “clean” calls, or by lease expiration.
    The distributed garbage collector will maintain a reference for each remote object exported in the local RMI Runtime, and this reference will be STRONG when the counter defined above is grater than zero, and WEAK when the counter is zero.
    This “changing” reference will avoid the local garbage collector for collecting the remote object when there are one or more than one remote references (stubs) for the remote object, and allow the object collection when there isn’t any remote reference to it.
    When a weak referenced remote object will be collected by local garbage collector, the DGC should call a kind of “unexport” method in the Remote Reference layer, in order to eliminate all information about that object (which no longer exists) from the RMI Runtime internal tables, and do the necessary cleanup in the Transport Layer (maybe closing the listening server socket and finishing the listening thread, as necessary).

    23/11/2005 – Gustavo Petri
    DGCAck:
    There are several unresolved issues about the DGCAck message: As stated in the Modula-3 Distributed Garbage Collector document, the DGCAck message will be used to avoid the early collection of an exported object. A DGCAck must be sent when a object containing Remote objects (it can be a Remote itself) is received as the return value of a remote method invocation, to the returning process. The DGCAck message it is aimed to maintain a "live" reference to the Remote object while the receiving process has not yet executed a dirty method on the Server of the reveived object, if the returning server would not maintain the "live" reference the Remote object could be garbage collected before the receiving client issues the first dirty call.
    Ideas:
    There is no need to send more than one DGCAck message per object (Remote or holding Remote instances). If any of the Remote instances (Stubs) received can not be "activated" (a successful dirty call), then the containing object can not be unmarshaled and a UnmarshalException will be thrown and the DGCAck will no need to be sent. We can also take as a policy to send a DGCAck for every returned value, whether it contains or not Remote instances. This would not violate the specification, and it would make the implementation more simple and transparent. Besides it does not generate overhead since, as stated in the specification, waiting for the DGCAck's is not in the critical path of the execution of RMI. This is not yet decided. If we chose to send a DGCAck only when the received object contains a Remote instance, there should be some way to know, at the returning server, wheter to wait or not for a DGCAck message.

    Registry Implementation Ideas

    RMI Registry Implementation Ideas

    07/05/2005 - Gonzalo Ortega

    The RMI registry is a very simple and ordinary RMI server (O’Reilly). It stores in a table a String (the UnicastObject server name) linked with a stub of that remote object, like any other RMI server. At the beginning we thought that the registry could hold a special type of stubs, but at the moment it seems that isn’t really true. The only tricky thing (apparently) is the fact that we don’t need a stub to contact it. One possible way of implementing this behavior is creating a special “well known static stub” for the registry object. This stub could be created from a new RemoteRef, using the hostname, port and the well-known ObjID defined for the Registry. This probably avoid the possibility of exporting two registries in the same port in a host, and allow the creation of stubs for registries that don’t even exist (?).


    TransporManager Implementation Ideas

    Transport Manager Implementation Ideas

    The TransportManager, provides the low level network services to the RemoteReferenceManager. It main purpose is to handle the Sockets and the Threads used by the RMI Runtime.
    We have defined a thin interface between the RemoteReferenceManager and the TransportManager. The idea behind this is to make a replaceable implementation of the TransportManager.
    We have chosen to left the management of the JRMP Protocol, and the administration of the Threads and Sockets in the TransportManager. This way we can easily replace diferent implementations of the Transport Layer switching for example between Multithreaded, SingleThreaded and pooled implementations of the request handlers.
    The specific messages of the JRMP protocol are also separated from the logical sequence of the comunication, which eventualy will allow us to modify the protocol without affecting the entire TransportManager.
    The current implementation of the TransportManager is single threaded (see SingleThreadedServer), and it is aimed to be a first aproach to RMI, to be replaced by a more efficient one.


    Activation Implementation Ideas

    10/11/2005 Daniel Gandara

    Activation spec is not clear at all, it looks like it is telling you an history, it is very vague about things like path to follow if something goes wrong, or the way it has to behave between client and server; at this point we have many questions regarding the way it should work, how are the stubs generated? are they the same as before (normal URO). Activation should be constructed above unicast remote object since this looks like the best and logic way to implement it in an evolutionary scenario; following this concept rmid looks like a regular URO which has an especific functionality an ability to activate other objects...

    15/11/2005 Daniel Gandara

    Problem: What about the stubs for activable objects? are they the same? are they generated different from other stubs? this will again give us a better understanding on the way is should be implemented, since we decided that the outputs from rmic are an extension to the spec, we'll check on the outputs..

    17/11/2005 Daniel Gandara

    outputs from rmic for activables looks exactly the same. This give us the idea that is the activation daemon how handles all the complexity and the client never get noticed about that; this way the client gets a reference to the activator (the activator's stub is the one registered on the naming service), but it has no sense to implement this having the client talk to the activator and then the activator to the activated object... client should be able to "somehow" talk directly to the activated object instead of the activator, once the object is active.



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